Fixed problem in IO dirreq/filereq, optimized code, nsExec with /CMD param to allow execute 16Bits DOS applications
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2762 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
da9d5eb4db
commit
21f668de9c
5 changed files with 91 additions and 88 deletions
|
@ -18,8 +18,6 @@
|
||||||
#include "../exdll/exdll.h"
|
#include "../exdll/exdll.h"
|
||||||
#undef popstring
|
#undef popstring
|
||||||
|
|
||||||
void * mini_memcpy(void *out, const void *in, int len);
|
|
||||||
void * mini_zeromem(void *in, int len);
|
|
||||||
|
|
||||||
static int popstring(char *str)
|
static int popstring(char *str)
|
||||||
{
|
{
|
||||||
|
@ -138,7 +136,7 @@ struct FieldType {
|
||||||
UINT nControlID;
|
UINT nControlID;
|
||||||
|
|
||||||
int nParentIdx; // this is used by the filerequest and dirrequest controls, used to store original windowproc for LINK
|
int nParentIdx; // this is used by the filerequest and dirrequest controls, used to store original windowproc for LINK
|
||||||
HANDLE hImage; // this is used by image/icon field to save the handle to the image, or used by LINK control to store the color
|
HANDLE hImage; // this is used by image/icon field to save the handle to the image
|
||||||
};
|
};
|
||||||
|
|
||||||
// initial buffer size. buffers will grow as required.
|
// initial buffer size. buffers will grow as required.
|
||||||
|
@ -434,56 +432,6 @@ bool SaveSettings(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BROWSE_WIDTH 15
|
#define BROWSE_WIDTH 15
|
||||||
|
|
||||||
void AddBrowseButtons() {
|
|
||||||
// this function loops through all the controls and if a filerequest or dirrequest
|
|
||||||
// control is found, then it adds the corresponding browse button.
|
|
||||||
// NOTE: this also resizes the text box created to make room for the button.
|
|
||||||
int nIdx;
|
|
||||||
FieldType *pNewField;
|
|
||||||
|
|
||||||
for (nIdx = nNumFields - 1; nIdx >= 0; nIdx--) {
|
|
||||||
// we loop down so we don't run into the newly added fields.
|
|
||||||
switch (pFields[nIdx].nType) {
|
|
||||||
case FIELD_FILEREQUEST:
|
|
||||||
case FIELD_DIRREQUEST:
|
|
||||||
// Insert button after edit, tabstop depends in creation order,
|
|
||||||
// with this trick browse button get tabstop after parent edit
|
|
||||||
if ( nIdx < nNumFields - 1 )
|
|
||||||
{
|
|
||||||
mini_memcpy(&pFields[nIdx+2], &pFields[nIdx+1], (nNumFields-nIdx-1)*sizeof(FieldType) );
|
|
||||||
for ( int i = nIdx+2; i < nNumFields; i++ )
|
|
||||||
{
|
|
||||||
if ( pFields[i].nType == FIELD_BROWSEBUTTON )
|
|
||||||
pFields[i].nParentIdx++; // Ohh! where is your dady :)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// After moving controls 1 position, don't forget to increment nNumFields at *end* of loop
|
|
||||||
pNewField = &pFields[nIdx+1];
|
|
||||||
mini_zeromem(pNewField, sizeof(FieldType)); // don't use settings from other control
|
|
||||||
pNewField->nControlID = 1200 + nNumFields;
|
|
||||||
pNewField->nParentIdx = nIdx;
|
|
||||||
pNewField->nType = FIELD_BROWSEBUTTON;
|
|
||||||
pNewField->nFlags = pFields[nIdx].nFlags & (FLAG_DISABLED | FLAG_NOTABSTOP);
|
|
||||||
//pNewField->pszListItems = NULL;
|
|
||||||
//pNewField->nMaxLength = 0;
|
|
||||||
//pNewField->nMinLength = 0;
|
|
||||||
pNewField->pszText = STRDUP(szBrowseButtonCaption); // needed for generic FREE
|
|
||||||
//pNewField->pszValidateText = NULL;
|
|
||||||
|
|
||||||
pNewField->rect.right = pFields[nIdx].rect.right;
|
|
||||||
pNewField->rect.left = pNewField->rect.right - BROWSE_WIDTH;
|
|
||||||
pNewField->rect.bottom = pFields[nIdx].rect.bottom;
|
|
||||||
pNewField->rect.top = pFields[nIdx].rect.top;
|
|
||||||
|
|
||||||
pFields[nIdx].rect.right = pNewField->rect.left - 3;
|
|
||||||
|
|
||||||
nNumFields++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char szResult[4096];
|
static char szResult[4096];
|
||||||
|
|
||||||
DWORD WINAPI myGetProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName)
|
DWORD WINAPI myGetProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName)
|
||||||
|
@ -502,7 +450,7 @@ char * WINAPI myGetProfileStringDup(LPCTSTR lpAppName, LPCTSTR lpKeyName)
|
||||||
|
|
||||||
bool ReadSettings(void) {
|
bool ReadSettings(void) {
|
||||||
static char szField[25];
|
static char szField[25];
|
||||||
int nIdx;
|
int nIdx, nCtrlIdx;
|
||||||
|
|
||||||
pszTitle = myGetProfileStringDup("Settings", "Title");
|
pszTitle = myGetProfileStringDup("Settings", "Title");
|
||||||
pszCancelButtonText = myGetProfileStringDup("Settings", "CancelButtonText");
|
pszCancelButtonText = myGetProfileStringDup("Settings", "CancelButtonText");
|
||||||
|
@ -525,7 +473,7 @@ bool ReadSettings(void) {
|
||||||
pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
|
pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(nIdx = 0; nIdx < nNumFields; nIdx++) {
|
for(nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
|
||||||
// Control types
|
// Control types
|
||||||
static TableEntry TypeTable[] = {
|
static TableEntry TypeTable[] = {
|
||||||
{ "LABEL", FIELD_LABEL },
|
{ "LABEL", FIELD_LABEL },
|
||||||
|
@ -574,7 +522,7 @@ bool ReadSettings(void) {
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
wsprintf(szField, "Field %d", nIdx + 1);
|
wsprintf(szField, "Field %d", nCtrlIdx + 1);
|
||||||
myGetProfileString(szField, "TYPE");
|
myGetProfileString(szField, "TYPE");
|
||||||
|
|
||||||
// Get the control type
|
// Get the control type
|
||||||
|
@ -671,9 +619,24 @@ bool ReadSettings(void) {
|
||||||
pFields[nIdx].hImage = (HANDLE)GetPrivateProfileInt(szField, "TxtColor", RGB(0,0,255), pszFilename);
|
pFields[nIdx].hImage = (HANDLE)GetPrivateProfileInt(szField, "TxtColor", RGB(0,0,255), pszFilename);
|
||||||
|
|
||||||
pFields[nIdx].nControlID = 1200 + nIdx;
|
pFields[nIdx].nControlID = 1200 + nIdx;
|
||||||
|
if ( pFields[nIdx].nType == FIELD_FILEREQUEST || pFields[nIdx].nType == FIELD_DIRREQUEST )
|
||||||
|
{
|
||||||
|
FieldType *pNewField = &pFields[nIdx+1];
|
||||||
|
pNewField->nControlID = 1200 + nIdx + 1;
|
||||||
|
pNewField->nParentIdx = nIdx;
|
||||||
|
pNewField->nType = FIELD_BROWSEBUTTON;
|
||||||
|
pNewField->nFlags = pFields[nIdx].nFlags & (FLAG_DISABLED | FLAG_NOTABSTOP);
|
||||||
|
pNewField->pszText = STRDUP(szBrowseButtonCaption); // needed for generic FREE
|
||||||
|
pNewField->rect.right = pFields[nIdx].rect.right;
|
||||||
|
pNewField->rect.left = pNewField->rect.right - BROWSE_WIDTH;
|
||||||
|
pNewField->rect.bottom = pFields[nIdx].rect.bottom;
|
||||||
|
pNewField->rect.top = pFields[nIdx].rect.top;
|
||||||
|
pFields[nIdx].rect.right = pNewField->rect.left - 3;
|
||||||
|
nNumFields++;
|
||||||
|
nIdx++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AddBrowseButtons();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -696,7 +659,7 @@ LRESULT WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (pFields[nIdx].nType == FIELD_LINK) {
|
} else if (pFields[nIdx].nType == FIELD_LINK) {
|
||||||
ShellExecute(hMainWindow, NULL, pFields[nIdx].pszState, NULL, NULL, SW_SHOWDEFAULT);
|
ShellExecute(hMainWindow, NULL, pFields[nIdx].pszState, NULL, NULL, SW_SHOWDEFAULT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -761,7 +724,7 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg,
|
||||||
if ( ( lpdis->itemState & ODS_FOCUS && lpdis->itemAction & ODA_DRAWENTIRE) || (lpdis->itemAction & ODA_FOCUS) ||
|
if ( ( lpdis->itemState & ODS_FOCUS && lpdis->itemAction & ODA_DRAWENTIRE) || (lpdis->itemAction & ODA_FOCUS) ||
|
||||||
(lpdis->itemAction & ODA_SELECT))
|
(lpdis->itemAction & ODA_SELECT))
|
||||||
DrawFocusRect(lpdis->hDC, &pFields[nIdx].rect);
|
DrawFocusRect(lpdis->hDC, &pFields[nIdx].rect);
|
||||||
|
|
||||||
SetTextColor(lpdis->hDC, (COLORREF)pFields[nIdx].hImage);
|
SetTextColor(lpdis->hDC, (COLORREF)pFields[nIdx].hImage);
|
||||||
|
|
||||||
pFields[nIdx].rect = lpdis->rcItem;
|
pFields[nIdx].rect = lpdis->rcItem;
|
||||||
|
@ -1363,23 +1326,3 @@ void ConvertNewLines(char *str) {
|
||||||
*p2 = 0;
|
*p2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * mini_memcpy(void *outBuf, const void *inBuf, int len)
|
|
||||||
{
|
|
||||||
char *c_out=(char*)outBuf+(len-1);
|
|
||||||
char *c_in=(char *)inBuf+(len-1);
|
|
||||||
while (len-- > 0)
|
|
||||||
{
|
|
||||||
*c_out--=*c_in--;
|
|
||||||
}
|
|
||||||
return outBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void * mini_zeromem(void *in, int len)
|
|
||||||
{
|
|
||||||
char *c_in=(char *)in;
|
|
||||||
while (len-- > 0)
|
|
||||||
{
|
|
||||||
*c_in++=0;
|
|
||||||
}
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,15 +6,15 @@ without opening a dos box.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
nsExec::Exec [/TIMEOUT=x] path
|
nsExec::Exec [/TIMEOUT=x] [/CMD] path
|
||||||
|
|
||||||
-or-
|
-or-
|
||||||
|
|
||||||
nsExec::ExecToLog [/TIMEOUT=x] path
|
nsExec::ExecToLog [/TIMEOUT=x] [/CMD] path
|
||||||
|
|
||||||
-or-
|
-or-
|
||||||
|
|
||||||
nsExec::ExecToStack [/TIMEOUT=x] path
|
nsExec::ExecToStack [/TIMEOUT=x] [/CMD] path
|
||||||
|
|
||||||
All functions are the same except ExecToLog will print the output
|
All functions are the same except ExecToLog will print the output
|
||||||
to the logwindow and ExecToStack will push up to ${NSIS_MAX_STRLEN}
|
to the logwindow and ExecToStack will push up to ${NSIS_MAX_STRLEN}
|
||||||
|
@ -26,6 +26,18 @@ process is received, the timeout value is reset and it will
|
||||||
again wait for more output using the timeout value. See Return
|
again wait for more output using the timeout value. See Return
|
||||||
Value for how to check if there was a timeout.
|
Value for how to check if there was a timeout.
|
||||||
|
|
||||||
|
The /CMD param is optional. The /CMD indicates that the exec procedure should use
|
||||||
|
command processor to execute the command, ie, %COMSPEC% path
|
||||||
|
|
||||||
|
*IMPORTANT NOTICE* The /CMD param should be used for 16bits MS-DOS applications
|
||||||
|
or applications that create windows, or any form of user interface
|
||||||
|
|
||||||
|
To ensure that command are executed without problems on all windows versions,
|
||||||
|
is recommended to use the following syntax:
|
||||||
|
|
||||||
|
nsExec::ExecToStack [OPTIONS] '"PATH" param1 param2 paramN'
|
||||||
|
|
||||||
|
This way the application path may contain non 8.3 paths (with spaces)
|
||||||
|
|
||||||
Return Value
|
Return Value
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -40,6 +40,7 @@ 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;
|
||||||
|
@ -69,23 +70,50 @@ BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lp
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TAB_REPLACE " "
|
||||||
|
#define TAB_REPLACE_SIZE (sizeof(TAB_REPLACE)-1)
|
||||||
|
|
||||||
void ExecScript(int log) {
|
void ExecScript(int log) {
|
||||||
char szRet[128] = "";
|
char szRet[128] = "";
|
||||||
|
char *pExec;
|
||||||
|
char sAux[MAX_PATH];
|
||||||
|
char *pRoot = NULL;
|
||||||
|
int nComSpecSize;
|
||||||
|
BOOL bUseComSpec=false;
|
||||||
|
|
||||||
|
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+1);
|
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+1);
|
||||||
if (!popstring(g_exec)) {
|
lstrcpy(g_exec, sAux);
|
||||||
|
pExec = g_exec + nComSpecSize - 1;
|
||||||
|
|
||||||
|
while ( !popstring(pExec) ) {
|
||||||
if (my_strstr(g_exec,"/TIMEOUT=")) {
|
if (my_strstr(g_exec,"/TIMEOUT=")) {
|
||||||
char *szTimeout = g_exec + 9;
|
char *szTimeout = g_exec + 9;
|
||||||
g_to = my_atoi(szTimeout);
|
g_to = my_atoi(szTimeout);
|
||||||
popstring(g_exec);
|
|
||||||
}
|
}
|
||||||
|
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),};
|
||||||
|
@ -128,7 +156,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,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) {
|
if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,0,NULL,pRoot,&si,&pi)) {
|
||||||
lstrcpy(szRet, "error");
|
lstrcpy(szRet, "error");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -160,12 +188,21 @@ void ExecScript(int log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(log & 2)) {
|
if (!(log & 2)) {
|
||||||
|
while ( p = my_strstr(p, "\t") )
|
||||||
|
{
|
||||||
|
mini_memcpy(p+TAB_REPLACE_SIZE, p+1, lstrlen(p));
|
||||||
|
lstrcpy(p, TAB_REPLACE);
|
||||||
|
p += TAB_REPLACE_SIZE;
|
||||||
|
*p = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
p = szUnusedBuf; // get the old left overs
|
||||||
while (lineBreak = my_strstr(p, "\r\n")) {
|
while (lineBreak = my_strstr(p, "\r\n")) {
|
||||||
*lineBreak = 0;
|
*lineBreak = 0;
|
||||||
LogMessage(p);
|
LogMessage(p);
|
||||||
p = lineBreak + 2;
|
p = lineBreak + 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf
|
// If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf
|
||||||
if (p != szUnusedBuf) {
|
if (p != szUnusedBuf) {
|
||||||
char *p2 = szUnusedBuf;
|
char *p2 = szUnusedBuf;
|
||||||
|
@ -270,3 +307,14 @@ unsigned int my_atoi(char *s) {
|
||||||
}
|
}
|
||||||
return (int)v;
|
return (int)v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void * mini_memcpy(void *outBuf, const void *inBuf, int len)
|
||||||
|
{
|
||||||
|
char *c_out=(char*)outBuf+(len-1);
|
||||||
|
char *c_in=(char *)inBuf+(len-1);
|
||||||
|
while (len-- > 0)
|
||||||
|
{
|
||||||
|
*c_out--=*c_in--;
|
||||||
|
}
|
||||||
|
return outBuf;
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue