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:
ramon18 2003-07-23 09:38:05 +00:00
parent a3c887d456
commit f7f575a8cb
2 changed files with 102 additions and 39 deletions

View file

@ -20,6 +20,7 @@ freely, subject to the following restrictions:
*/
#include <windows.h>
#include <commctrl.h>
#include <Winnt.h>
#include "../exdll/exdll.h"
#ifndef true
@ -35,12 +36,10 @@ HWND g_hwndList;
char * g_exec;
unsigned int g_to;
void ExecScript(BOOL log);
void LogMessage(const char *pStr);
char *my_strstr(const char *string, const char *strCharSet);
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) {
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) {
g_hInst = hInst;
return TRUE;
}
#define TAB_REPLACE " "
#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) {
char szRet[128] = "";
char *pExec;
char sAux[MAX_PATH];
char *pRoot = NULL;
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_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,"#32770",NULL),NULL,"SysListView32",NULL);
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1);
lstrcpy(g_exec, sAux);
pExec = g_exec + nComSpecSize - 1;
while ( !popstring(pExec) ) {
if (my_strstr(g_exec,"/TIMEOUT=")) {
char *szTimeout = g_exec + 9;
g_to = my_atoi(szTimeout);
}
else if (my_strstr(g_exec,"/CMD")) {
bUseComSpec = true;
}
else
break;
pExec = g_exec + nComSpecSize - 1; *pExec = ' '; pExec++;
popstring(pExec);
if ( my_strstr(pExec, "/TIMEOUT=") ) {
char *szTimeout = pExec + 9;
g_to = my_atoi(szTimeout);
popstring(pExec);
}
if (!pExec[0] )
if (!g_exec[0] )
{
lstrcpy(szRet, "error");
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),};
SECURITY_ATTRIBUTES sa={sizeof(sa),};
@ -143,7 +165,8 @@ void ExecScript(int log) {
SetSecurityDescriptorDacl(&sd,true,NULL,false);
sa.lpSecurityDescriptor = &sd;
}
else sa.lpSecurityDescriptor = NULL;
else
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = true;
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) {
lstrcpy(szRet, "error");
@ -156,7 +179,7 @@ void ExecScript(int log) {
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = 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");
goto done;
}
@ -190,7 +213,14 @@ void ExecScript(int log) {
if (!(log & 2)) {
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);
p += TAB_REPLACE_SIZE;
*p = ' ';
@ -227,6 +257,8 @@ void ExecScript(int log) {
done:
if (log & 2) pushstring(szUnusedBuf);
if (log & 1 && *szUnusedBuf) LogMessage(szUnusedBuf);
if ( dwExit == STATUS_ILLEGAL_INSTRUCTION )
lstrcpy(szRet, "error");
if (!szRet[0]) wsprintf(szRet,"%d",dwExit);
pushstring(szRet);
CloseHandle(pi.hThread);
@ -308,13 +340,44 @@ unsigned int my_atoi(char *s) {
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);
char *c_in=(char *)inBuf+(len-1);
while (len-- > 0)
DWORD Ret;
STARTUPINFO si = {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;
}