nsExec create a temp console app to spawn commands, can run applications with user interface and also 16bit DOS
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2765 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
a3c887d456
commit
f7f575a8cb
2 changed files with 102 additions and 39 deletions
|
@ -20,6 +20,7 @@ freely, subject to the following restrictions:
|
||||||
*/
|
*/
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include <Winnt.h>
|
||||||
#include "../exdll/exdll.h"
|
#include "../exdll/exdll.h"
|
||||||
|
|
||||||
#ifndef true
|
#ifndef true
|
||||||
|
@ -35,12 +36,10 @@ HWND g_hwndList;
|
||||||
char * g_exec;
|
char * g_exec;
|
||||||
unsigned int g_to;
|
unsigned int g_to;
|
||||||
|
|
||||||
|
|
||||||
void ExecScript(BOOL log);
|
void ExecScript(BOOL log);
|
||||||
void LogMessage(const char *pStr);
|
void LogMessage(const char *pStr);
|
||||||
char *my_strstr(const char *string, const char *strCharSet);
|
char *my_strstr(const char *string, const char *strCharSet);
|
||||||
unsigned int my_atoi(char *s);
|
unsigned int my_atoi(char *s);
|
||||||
void * mini_memcpy(void *outBuf, const void *inBuf, int len);
|
|
||||||
|
|
||||||
void __declspec(dllexport) Exec(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) {
|
void __declspec(dllexport) Exec(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) {
|
||||||
g_hwndParent=hwndParent;
|
g_hwndParent=hwndParent;
|
||||||
|
@ -66,54 +65,77 @@ void __declspec(dllexport) ExecToStack(HWND hwndParent, int string_size, char *v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HINSTANCE g_hInst;
|
||||||
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) {
|
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) {
|
||||||
|
g_hInst = hInst;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TAB_REPLACE " "
|
#define TAB_REPLACE " "
|
||||||
#define TAB_REPLACE_SIZE (sizeof(TAB_REPLACE)-1)
|
#define TAB_REPLACE_SIZE (sizeof(TAB_REPLACE)-1)
|
||||||
|
|
||||||
|
// Turn a pair of chars into a word
|
||||||
|
// Turn four chars into a dword
|
||||||
|
#ifdef __BIG_ENDIAN__ // Not very likely, but, still...
|
||||||
|
#define CHAR2_TO_WORD(a,b) (((WORD)(b))|((a)<<8))
|
||||||
|
#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(c,d))|(CHAR2_TO_WORD(a,b)<<16))
|
||||||
|
#else
|
||||||
|
#define CHAR2_TO_WORD(a,b) (((WORD)(a))|((b)<<8))
|
||||||
|
#define CHAR4_TO_DWORD(a,b,c,d) (((DWORD)CHAR2_TO_WORD(a,b))|(CHAR2_TO_WORD(c,d)<<16))
|
||||||
|
#endif
|
||||||
|
|
||||||
void ExecScript(int log) {
|
void ExecScript(int log) {
|
||||||
char szRet[128] = "";
|
char szRet[128] = "";
|
||||||
char *pExec;
|
char *pExec;
|
||||||
char sAux[MAX_PATH];
|
|
||||||
char *pRoot = NULL;
|
|
||||||
int nComSpecSize;
|
int nComSpecSize;
|
||||||
BOOL bUseComSpec=false;
|
char meDLLPath[MAX_PATH];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
nComSpecSize = GetModuleFileName(g_hInst, meDLLPath, MAX_PATH);
|
||||||
|
p = meDLLPath + nComSpecSize - 1;
|
||||||
|
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1);
|
||||||
|
|
||||||
|
while ( *p && *p != '\\' )
|
||||||
|
p--;
|
||||||
|
if ( p )
|
||||||
|
*p = 0;
|
||||||
|
GetTempFileName(meDLLPath, "ns", 0, g_exec);
|
||||||
|
*p = '\\';
|
||||||
|
if ( CopyFile(meDLLPath, g_exec, FALSE) )
|
||||||
|
{
|
||||||
|
HANDLE hFile, hMapping;
|
||||||
|
PIMAGE_NT_HEADERS pNTHeaders;
|
||||||
|
hFile = CreateFile(g_exec, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0);
|
||||||
|
hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
|
||||||
|
pNTHeaders = (PIMAGE_NT_HEADERS)MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
|
||||||
|
if ( pNTHeaders )
|
||||||
|
{
|
||||||
|
pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE*)pNTHeaders + ((PIMAGE_DOS_HEADER)pNTHeaders)->e_lfanew);
|
||||||
|
pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED |
|
||||||
|
IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_RELOCS_STRIPPED;
|
||||||
|
pNTHeaders->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||||
|
pNTHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD)WinMain - (DWORD)g_hInst;
|
||||||
|
UnmapViewOfFile(pNTHeaders);
|
||||||
|
}
|
||||||
|
CloseHandle(hMapping);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
}
|
||||||
|
|
||||||
nComSpecSize = ExpandEnvironmentStrings("%ComSpec% /c ", sAux, MAX_PATH);
|
|
||||||
g_to = 0; // default is no timeout
|
g_to = 0; // default is no timeout
|
||||||
g_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,"#32770",NULL),NULL,"SysListView32",NULL);
|
g_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,"#32770",NULL),NULL,"SysListView32",NULL);
|
||||||
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1);
|
pExec = g_exec + nComSpecSize - 1; *pExec = ' '; pExec++;
|
||||||
lstrcpy(g_exec, sAux);
|
popstring(pExec);
|
||||||
pExec = g_exec + nComSpecSize - 1;
|
if ( my_strstr(pExec, "/TIMEOUT=") ) {
|
||||||
|
char *szTimeout = pExec + 9;
|
||||||
while ( !popstring(pExec) ) {
|
g_to = my_atoi(szTimeout);
|
||||||
if (my_strstr(g_exec,"/TIMEOUT=")) {
|
popstring(pExec);
|
||||||
char *szTimeout = g_exec + 9;
|
|
||||||
g_to = my_atoi(szTimeout);
|
|
||||||
}
|
|
||||||
else if (my_strstr(g_exec,"/CMD")) {
|
|
||||||
bUseComSpec = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (!g_exec[0] )
|
||||||
if (!pExec[0] )
|
|
||||||
{
|
{
|
||||||
lstrcpy(szRet, "error");
|
lstrcpy(szRet, "error");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( bUseComSpec )
|
|
||||||
{
|
|
||||||
GetWindowsDirectory(sAux, MAX_PATH); // UNC paths not supported on cmd.exe / command.com
|
|
||||||
pRoot = sAux;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lstrcpy(g_exec, pExec);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
STARTUPINFO si={sizeof(si),};
|
STARTUPINFO si={sizeof(si),};
|
||||||
SECURITY_ATTRIBUTES sa={sizeof(sa),};
|
SECURITY_ATTRIBUTES sa={sizeof(sa),};
|
||||||
|
@ -143,7 +165,8 @@ void ExecScript(int log) {
|
||||||
SetSecurityDescriptorDacl(&sd,true,NULL,false);
|
SetSecurityDescriptorDacl(&sd,true,NULL,false);
|
||||||
sa.lpSecurityDescriptor = &sd;
|
sa.lpSecurityDescriptor = &sd;
|
||||||
}
|
}
|
||||||
else sa.lpSecurityDescriptor = NULL;
|
else
|
||||||
|
sa.lpSecurityDescriptor = NULL;
|
||||||
sa.bInheritHandle = true;
|
sa.bInheritHandle = true;
|
||||||
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) {
|
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) {
|
||||||
lstrcpy(szRet, "error");
|
lstrcpy(szRet, "error");
|
||||||
|
@ -156,7 +179,7 @@ void ExecScript(int log) {
|
||||||
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
si.hStdOutput = newstdout;
|
si.hStdOutput = newstdout;
|
||||||
si.hStdError = newstdout;
|
si.hStdError = newstdout;
|
||||||
if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,0,NULL,pRoot,&si,&pi)) {
|
if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) {
|
||||||
lstrcpy(szRet, "error");
|
lstrcpy(szRet, "error");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -190,7 +213,14 @@ void ExecScript(int log) {
|
||||||
if (!(log & 2)) {
|
if (!(log & 2)) {
|
||||||
while ( p = my_strstr(p, "\t") )
|
while ( p = my_strstr(p, "\t") )
|
||||||
{
|
{
|
||||||
mini_memcpy(p+TAB_REPLACE_SIZE, p+1, lstrlen(p));
|
int len = lstrlen(p);
|
||||||
|
char *c_out=(char*)p+TAB_REPLACE_SIZE+(len-1);
|
||||||
|
char *c_in=(char *)p+1+(len-1);
|
||||||
|
while (len-- > 0)
|
||||||
|
{
|
||||||
|
*c_out--=*c_in--;
|
||||||
|
}
|
||||||
|
|
||||||
lstrcpy(p, TAB_REPLACE);
|
lstrcpy(p, TAB_REPLACE);
|
||||||
p += TAB_REPLACE_SIZE;
|
p += TAB_REPLACE_SIZE;
|
||||||
*p = ' ';
|
*p = ' ';
|
||||||
|
@ -227,6 +257,8 @@ void ExecScript(int log) {
|
||||||
done:
|
done:
|
||||||
if (log & 2) pushstring(szUnusedBuf);
|
if (log & 2) pushstring(szUnusedBuf);
|
||||||
if (log & 1 && *szUnusedBuf) LogMessage(szUnusedBuf);
|
if (log & 1 && *szUnusedBuf) LogMessage(szUnusedBuf);
|
||||||
|
if ( dwExit == STATUS_ILLEGAL_INSTRUCTION )
|
||||||
|
lstrcpy(szRet, "error");
|
||||||
if (!szRet[0]) wsprintf(szRet,"%d",dwExit);
|
if (!szRet[0]) wsprintf(szRet,"%d",dwExit);
|
||||||
pushstring(szRet);
|
pushstring(szRet);
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
@ -308,13 +340,44 @@ unsigned int my_atoi(char *s) {
|
||||||
return (int)v;
|
return (int)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * mini_memcpy(void *outBuf, const void *inBuf, int len)
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
char *c_out=(char*)outBuf+(len-1);
|
DWORD Ret;
|
||||||
char *c_in=(char *)inBuf+(len-1);
|
STARTUPINFO si = {0};
|
||||||
while (len-- > 0)
|
PROCESS_INFORMATION pi = {0};
|
||||||
|
char command_line[1024];
|
||||||
|
char seekchar=' ';
|
||||||
|
char *cmdline;
|
||||||
|
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
// Make child process use this app's standard files. Not needed !??
|
||||||
|
//si.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
//si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
|
||||||
|
//si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||||
|
//si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
|
||||||
|
lstrcpyn(command_line, GetCommandLine(), 1024);
|
||||||
|
|
||||||
|
cmdline = command_line;
|
||||||
|
if (*cmdline == '\"') seekchar = *cmdline++;
|
||||||
|
|
||||||
|
while (*cmdline && *cmdline != seekchar) cmdline=CharNext(cmdline);
|
||||||
|
cmdline=CharNext(cmdline);
|
||||||
|
|
||||||
|
Ret = CreateProcess (NULL, cmdline,
|
||||||
|
NULL, NULL,
|
||||||
|
TRUE, 0,
|
||||||
|
NULL, NULL,
|
||||||
|
&si, &pi
|
||||||
|
);
|
||||||
|
|
||||||
|
if (Ret)
|
||||||
{
|
{
|
||||||
*c_out--=*c_in--;
|
WaitForSingleObject (pi.hProcess, INFINITE);
|
||||||
|
GetExitCodeProcess(pi.hProcess, &Ret);
|
||||||
|
CloseHandle (pi.hProcess);
|
||||||
|
CloseHandle (pi.hThread);
|
||||||
|
return Ret;
|
||||||
}
|
}
|
||||||
return outBuf;
|
else
|
||||||
|
return STATUS_ILLEGAL_INSTRUCTION;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue