diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp index bdd3ef3f..0f519997 100644 --- a/Contrib/InstallOptions/InstallerOptions.cpp +++ b/Contrib/InstallOptions/InstallerOptions.cpp @@ -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; -} diff --git a/Contrib/nsExec/nsExec.txt b/Contrib/nsExec/nsExec.txt index dcf06c92..5f1e2f75 100644 --- a/Contrib/nsExec/nsExec.txt +++ b/Contrib/nsExec/nsExec.txt @@ -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 ------------ diff --git a/Contrib/nsExec/nsexec.c b/Contrib/nsExec/nsexec.c index e0fcc614..8547857e 100644 --- a/Contrib/nsExec/nsexec.c +++ b/Contrib/nsExec/nsexec.c @@ -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; +} diff --git a/Plugins/InstallOptions.dll b/Plugins/InstallOptions.dll index 23434d82..cc206d57 100644 Binary files a/Plugins/InstallOptions.dll and b/Plugins/InstallOptions.dll differ diff --git a/Plugins/nsExec.dll b/Plugins/nsExec.dll index 101f64b4..1dd8bf93 100644 Binary files a/Plugins/nsExec.dll and b/Plugins/nsExec.dll differ