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:
ramon18 2003-07-21 19:48:48 +00:00
parent da9d5eb4db
commit 21f668de9c
5 changed files with 91 additions and 88 deletions

View file

@ -18,8 +18,6 @@
#include "../exdll/exdll.h"
#undef popstring
void * mini_memcpy(void *out, const void *in, int len);
void * mini_zeromem(void *in, int len);
static int popstring(char *str)
{
@ -138,7 +136,7 @@ struct FieldType {
UINT nControlID;
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.
@ -434,56 +432,6 @@ bool SaveSettings(void) {
}
#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];
DWORD WINAPI myGetProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName)
@ -502,7 +450,7 @@ char * WINAPI myGetProfileStringDup(LPCTSTR lpAppName, LPCTSTR lpKeyName)
bool ReadSettings(void) {
static char szField[25];
int nIdx;
int nIdx, nCtrlIdx;
pszTitle = myGetProfileStringDup("Settings", "Title");
pszCancelButtonText = myGetProfileStringDup("Settings", "CancelButtonText");
@ -525,7 +473,7 @@ bool ReadSettings(void) {
pFields = (FieldType *)MALLOC(sizeof(FieldType)*2*nNumFields);
}
for(nIdx = 0; nIdx < nNumFields; nIdx++) {
for(nIdx = 0, nCtrlIdx = 0; nCtrlIdx < nNumFields; nCtrlIdx++, nIdx++) {
// Control types
static TableEntry TypeTable[] = {
{ "LABEL", FIELD_LABEL },
@ -574,7 +522,7 @@ bool ReadSettings(void) {
{ NULL, 0 }
};
wsprintf(szField, "Field %d", nIdx + 1);
wsprintf(szField, "Field %d", nCtrlIdx + 1);
myGetProfileString(szField, "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].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;
}
@ -696,7 +659,7 @@ LRESULT WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) {
}
break;
} 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;
@ -761,7 +724,7 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg,
if ( ( lpdis->itemState & ODS_FOCUS && lpdis->itemAction & ODA_DRAWENTIRE) || (lpdis->itemAction & ODA_FOCUS) ||
(lpdis->itemAction & ODA_SELECT))
DrawFocusRect(lpdis->hDC, &pFields[nIdx].rect);
SetTextColor(lpdis->hDC, (COLORREF)pFields[nIdx].hImage);
pFields[nIdx].rect = lpdis->rcItem;
@ -1363,23 +1326,3 @@ void ConvertNewLines(char *str) {
*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;
}

View file

@ -6,15 +6,15 @@ without opening a dos box.
Usage
-----
nsExec::Exec [/TIMEOUT=x] path
nsExec::Exec [/TIMEOUT=x] [/CMD] path
-or-
nsExec::ExecToLog [/TIMEOUT=x] path
nsExec::ExecToLog [/TIMEOUT=x] [/CMD] path
-or-
nsExec::ExecToStack [/TIMEOUT=x] path
nsExec::ExecToStack [/TIMEOUT=x] [/CMD] path
All functions are the same except ExecToLog will print the output
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
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
------------

View file

@ -40,6 +40,7 @@ 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;
@ -69,23 +70,50 @@ BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lp
return TRUE;
}
#define TAB_REPLACE " "
#define TAB_REPLACE_SIZE (sizeof(TAB_REPLACE)-1)
void ExecScript(int log) {
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_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,"#32770",NULL),NULL,"SysListView32",NULL);
g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+1);
if (!popstring(g_exec)) {
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);
popstring(g_exec);
}
else if (my_strstr(g_exec,"/CMD")) {
bUseComSpec = true;
}
else
break;
}
if (!g_exec[0]) {
if (!pExec[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),};
@ -128,7 +156,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,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) {
if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,0,NULL,pRoot,&si,&pi)) {
lstrcpy(szRet, "error");
goto done;
}
@ -160,12 +188,21 @@ void ExecScript(int log) {
}
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")) {
*lineBreak = 0;
LogMessage(p);
p = lineBreak + 2;
}
// If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf
if (p != szUnusedBuf) {
char *p2 = szUnusedBuf;
@ -270,3 +307,14 @@ unsigned int my_atoi(char *s) {
}
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.