static bool CheckWow64( void ) { DWORD version = GetVersion(); if( version < 0x80000000 && LOBYTE( LOWORD( version ) ) >= 5 && IsWOW64() ) { char *msg = "You are using 32-bit installer on 64-bit host\n" "It is recommended to use 64-bit installer\n" "\ton 64-bit host\n" "Press OK button to continue with installation\n" "\tor Cancel button to abort it\n"; InitGlobalVarList(); SetVariableByName( "IDS_USEINST64BIT", "%s"); if( MsgBox( NULL, "IDS_USEINST64BIT", GUI_OK_CANCEL, msg ) != GUI_RET_OK ) { /* return TRUE to terminate installer */ return( TRUE ); } } return( FALSE ); }
void ExecScript(int log) { char szRet[128] = ""; char meDLLPath[MAX_PATH]; char *executor; char *g_exec; char *pExec; unsigned int g_to; BOOL bOEM; if (!IsWOW64()) { char *p; int nComSpecSize; nComSpecSize = GetModuleFileName(g_hInst, meDLLPath, MAX_PATH) + 2; // 2 chars for quotes g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+nComSpecSize+2); // 1 for space, 1 for null p = meDLLPath + nComSpecSize - 2; // point p at null char of meDLLPath *g_exec = '"'; executor = g_exec + 1; do { if (*p == '\\') break; p = CharPrev(meDLLPath, p); } while (p > meDLLPath); if (p == meDLLPath) { // bad path pushstring("error"); GlobalFree(g_exec); return; } *p = 0; GetTempFileName(meDLLPath, "ns", 0, executor); *p = '\\'; if (CopyFile(meDLLPath, executor, FALSE)) { HANDLE hFile, hMapping; LPBYTE pMapView; PIMAGE_NT_HEADERS pNTHeaders; hFile = CreateFile(executor, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0); hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); pMapView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0); if (pMapView) { pNTHeaders = (PIMAGE_NT_HEADERS)(pMapView + ((PIMAGE_DOS_HEADER)pMapView)->e_lfanew); pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE; pNTHeaders->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; pNTHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD)WinMain - (DWORD)g_hInst; UnmapViewOfFile(pMapView); } CloseHandle(hMapping); CloseHandle(hFile); } lstrcat(g_exec, "\""); // add space pExec = g_exec + lstrlen(g_exec); *pExec = ' '; pExec++; } else { executor = NULL; g_exec = (char *)GlobalAlloc(GPTR, sizeof(char)*g_stringsize+1); // 1 for null pExec = g_exec; } g_to = 0; // default is no timeout bOEM = FALSE; // default is no OEM->ANSI conversion g_hwndList = NULL; if (g_hwndParent) g_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,"#32770",NULL),NULL,"SysListView32",NULL); params: popstring(pExec); if (my_strstr(pExec, "/TIMEOUT=") == pExec) { char *szTimeout = pExec + 9; g_to = my_atoi(szTimeout); *pExec = 0; goto params; } if (!lstrcmpi(pExec, "/OEM")) { bOEM = TRUE; *pExec = 0; goto params; } if (!pExec[0]) { pushstring("error"); *(pExec-2) = '\0'; // skip space and quote if (executor) DeleteFile(executor); GlobalFree(g_exec); return; } { STARTUPINFO si={sizeof(si),}; SECURITY_ATTRIBUTES sa={sizeof(sa),}; SECURITY_DESCRIPTOR sd={0,}; PROCESS_INFORMATION pi={0,}; OSVERSIONINFO osv={sizeof(osv)}; HANDLE newstdout=0,read_stdout=0; HANDLE newstdin=0,read_stdin=0; DWORD dwRead = 1; DWORD dwExit = 0; DWORD dwWait = WAIT_TIMEOUT; DWORD dwLastOutput; static char szBuf[1024]; HGLOBAL hUnusedBuf = NULL; char *szUnusedBuf = 0; if (log) { hUnusedBuf = GlobalAlloc(GHND, log & 2 ? g_stringsize : sizeof(szBuf)*4); if (!hUnusedBuf) { lstrcpy(szRet, "error"); goto done; } szUnusedBuf = (char *)GlobalLock(hUnusedBuf); } GetVersionEx(&osv); if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT) { InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd,true,NULL,false); sa.lpSecurityDescriptor = &sd; } else sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = true; if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) { lstrcpy(szRet, "error"); goto done; } if (!CreatePipe(&read_stdin,&newstdin,&sa,0)) { lstrcpy(szRet, "error"); goto done; } GetStartupInfo(&si); si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdInput = newstdin; si.hStdOutput = newstdout; si.hStdError = newstdout; if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) { lstrcpy(szRet, "error"); goto done; } dwLastOutput = GetTickCount(); while (dwWait != WAIT_OBJECT_0 || dwRead) { PeekNamedPipe(read_stdout, 0, 0, 0, &dwRead, NULL); if (dwRead) { dwLastOutput = GetTickCount(); ReadFile(read_stdout, szBuf, sizeof(szBuf)-1, &dwRead, NULL); szBuf[dwRead] = 0; if (log) { char *p, *p2; SIZE_T iReqLen = lstrlen(szBuf) + lstrlen(szUnusedBuf); if (GlobalSize(hUnusedBuf) < iReqLen && (iReqLen < g_stringsize || !(log & 2))) { GlobalUnlock(hUnusedBuf); hUnusedBuf = GlobalReAlloc(hUnusedBuf, iReqLen+sizeof(szBuf), GHND); if (!hUnusedBuf) { lstrcpy(szRet, "error"); break; } szUnusedBuf = (char *)GlobalLock(hUnusedBuf); } p = szUnusedBuf; // get the old left overs if (iReqLen < g_stringsize || !(log & 2)) lstrcat(p, szBuf); else { lstrcpyn(p + lstrlen(p), szBuf, g_stringsize - lstrlen(p)); } if (!(log & 2)) { while ((p = my_strstr(p, "\t"))) { if ((int)(p - szUnusedBuf) > (int)(GlobalSize(hUnusedBuf) - TAB_REPLACE_SIZE - 1)) { *p++ = ' '; } else { int len = lstrlen(p); char *c_out=(char*)p+TAB_REPLACE_SIZE+len; char *c_in=(char *)p+len; while (len-- > 0) { *c_out--=*c_in--; } lstrcpy(p, TAB_REPLACE); p += TAB_REPLACE_SIZE; *p = ' '; } } p = szUnusedBuf; // get the old left overs for (p2 = p; *p2;) { if (*p2 == '\r') { *p2++ = 0; continue; } if (*p2 == '\n') { *p2 = 0; while (!*p && p != p2) p++; LogMessage(p, bOEM); p = ++p2; continue; } p2 = CharNext(p2); } // If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf if (p != szUnusedBuf) { char *p2 = szUnusedBuf; while (*p) *p2++ = *p++; *p2 = 0; } } } } else { if (g_to && GetTickCount() > dwLastOutput+g_to) { TerminateProcess(pi.hProcess, -1); lstrcpy(szRet, "timeout"); } else Sleep(LOOPTIMEOUT); } dwWait = WaitForSingleObject(pi.hProcess, 0); GetExitCodeProcess(pi.hProcess, &dwExit); PeekNamedPipe(read_stdout, 0, 0, 0, &dwRead, NULL); } done: if (log & 2) pushstring(szUnusedBuf); if (log & 1 && *szUnusedBuf) LogMessage(szUnusedBuf, bOEM); if ( dwExit == STATUS_ILLEGAL_INSTRUCTION ) lstrcpy(szRet, "error"); if (!szRet[0]) wsprintf(szRet,"%d",dwExit); pushstring(szRet); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(newstdout); CloseHandle(read_stdout); CloseHandle(newstdin); CloseHandle(read_stdin); *(pExec-2) = '\0'; // skip space and quote if (executor) DeleteFile(executor); GlobalFree(g_exec); if (log) { GlobalUnlock(hUnusedBuf); GlobalFree(hUnusedBuf); } } }
void ExecScript(int log) { TCHAR szRet[128] = _T(""); TCHAR meDLLPath[MAX_PATH]; TCHAR *executor; TCHAR *g_exec; TCHAR *pExec; unsigned int g_to; BOOL bOEM; if (!IsWOW64()) { TCHAR* p; int nComSpecSize; nComSpecSize = GetModuleFileName(g_hInst, meDLLPath, MAX_PATH) + 2; // 2 chars for quotes g_exec = (TCHAR *)GlobalAlloc(GPTR, sizeof(TCHAR)*(g_stringsize+nComSpecSize+2)); // 1 for space, 1 for null p = meDLLPath + nComSpecSize - 2; // point p at null char of meDLLPath *g_exec = _T('"'); executor = g_exec + 1; // Look for the last '\' in path. do { if (*p == _T('\\')) break; p = CharPrev(meDLLPath, p); } while (p > meDLLPath); if (p == meDLLPath) { // bad path pushstring(_T("error")); GlobalFree(g_exec); return; } *p = 0; GetTempFileName(meDLLPath, _T("ns"), 0, executor); // executor = new temp file name in module path. *p = _T('\\'); if (CopyFile(meDLLPath, executor, FALSE)) // copy current DLL to temp file in module path. { HANDLE hFile, hMapping; LPBYTE pMapView; PIMAGE_NT_HEADERS pNTHeaders; hFile = CreateFile(executor, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,0, 0); hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); pMapView = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0); if (pMapView) { pNTHeaders = (PIMAGE_NT_HEADERS)(pMapView + ((PIMAGE_DOS_HEADER)pMapView)->e_lfanew); // Turning the copied DLL into a stripped down executable. pNTHeaders->FileHeader.Characteristics = IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE; // Windows character-mode user interface (CUI) subsystem. pNTHeaders->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; // g_hInst is assumed to be the very base of the DLL in memory. // WinMain will have the address of the WinMain function in memory. // Getting the difference gets you the relative location of the // WinMain function. pNTHeaders->OptionalHeader.AddressOfEntryPoint = (DWORD) ((DWORD_PTR)AsExeWinMain - (DWORD_PTR)g_hInst); UnmapViewOfFile(pMapView); } CloseHandle(hMapping); CloseHandle(hFile); } lstrcat(g_exec, _T("\"")); // add space pExec = g_exec + lstrlen(g_exec); *pExec = _T(' '); pExec++; } else { executor = NULL; g_exec = (TCHAR *)GlobalAlloc(GPTR, sizeof(TCHAR)*(g_stringsize+1)); // 1 for NULL pExec = g_exec; } g_to = 0; // default is no timeout bOEM = FALSE; // default is no OEM->ANSI conversion g_hwndList = NULL; // g_hwndParent = the caller, usually NSIS installer. if (g_hwndParent) // The window class name for dialog boxes is "#32770" g_hwndList = FindWindowEx(FindWindowEx(g_hwndParent,NULL,_T("#32770"),NULL),NULL,_T("SysListView32"),NULL); // g_exec is the complete command to run: It has the copy of this DLL turned // into an executable right now. params: // Get the command I need to run from the NSIS stack. popstring(pExec); if (my_strstr(pExec, _T("/TIMEOUT=")) == pExec) { TCHAR *szTimeout = pExec + 9; g_to = my_atoi(szTimeout); *pExec = 0; goto params; } if (!lstrcmpi(pExec, _T("/OEM"))) { bOEM = TRUE; *pExec = 0; goto params; } if (!pExec[0]) { pushstring(_T("error")); if (pExec-2 >= g_exec) *(pExec-2) = _T('\0'); // skip space and quote if (executor) DeleteFile(executor); GlobalFree(g_exec); return; } // Got all the params off the stack. { STARTUPINFO si={sizeof(si),}; SECURITY_ATTRIBUTES sa={sizeof(sa),}; SECURITY_DESCRIPTOR sd={0,}; PROCESS_INFORMATION pi={0,}; const BOOL isNT = sizeof(void*) > 4 || (GetVersion() < 0x80000000); HANDLE newstdout=0,read_stdout=0; HANDLE newstdin=0,read_stdin=0; DWORD dwRead = 1; DWORD dwExit = 0; DWORD dwWait = WAIT_TIMEOUT; DWORD dwLastOutput; static TCHAR szBuf[1024]; #ifdef _UNICODE static char ansiBuf[1024]; #endif HGLOBAL hUnusedBuf = NULL; TCHAR *szUnusedBuf = 0; if (log) { hUnusedBuf = GlobalAlloc(GHND, log & 2 ? (g_stringsize*sizeof(TCHAR)) : sizeof(szBuf)*4); // Note: will not grow if (log & 2) if (!hUnusedBuf) { lstrcpy(szRet, _T("error")); goto done; } szUnusedBuf = (TCHAR *)GlobalLock(hUnusedBuf); } sa.bInheritHandle = true; sa.lpSecurityDescriptor = NULL; if (isNT) { InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd,true,NULL,false); sa.lpSecurityDescriptor = &sd; } if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) { lstrcpy(szRet, _T("error")); goto done; } if (!CreatePipe(&read_stdin,&newstdin,&sa,0)) { lstrcpy(szRet, _T("error")); goto done; } GetStartupInfo(&si); si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; si.hStdInput = newstdin; si.hStdOutput = newstdout; si.hStdError = newstdout; if (!CreateProcess(NULL,g_exec,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) { lstrcpy(szRet, _T("error")); goto done; } dwLastOutput = GetTickCount(); // Now I'm talking with an executable copy of myself. while (dwWait != WAIT_OBJECT_0 || dwRead) { PeekNamedPipe(read_stdout, 0, 0, 0, &dwRead, NULL); if (dwRead) { dwLastOutput = GetTickCount(); #ifdef _UNICODE ReadFile(read_stdout, ansiBuf, sizeof(ansiBuf)-1, &dwRead, NULL); ansiBuf[dwRead] = 0; WideConvertIfASCII(ansiBuf, dwRead, szBuf, sizeof(szBuf)/sizeof(szBuf[0])); #else ReadFile(read_stdout, szBuf, sizeof(szBuf)-1, &dwRead, NULL); szBuf[dwRead] = '\0'; #endif if (log) { if (log & 2) { lstrcpyn(szUnusedBuf + lstrlen(szUnusedBuf), szBuf, g_stringsize - lstrlen(szUnusedBuf)); } else { TCHAR *p, *p2; SIZE_T iReqLen = lstrlen(szBuf) + lstrlen(szUnusedBuf) + 1; if (GlobalSize(hUnusedBuf) < iReqLen*sizeof(TCHAR)) { GlobalUnlock(hUnusedBuf); hUnusedBuf = GlobalReAlloc(hUnusedBuf, iReqLen*sizeof(TCHAR)+sizeof(szBuf), GHND); if (!hUnusedBuf) { lstrcpy(szRet, _T("error")); break; } szUnusedBuf = (TCHAR *)GlobalLock(hUnusedBuf); } p = szUnusedBuf; // get the old left overs lstrcat(p, szBuf); while ((p = my_strstr(p, _T("\t")))) { if ((int)(p - szUnusedBuf) > (int)(GlobalSize(hUnusedBuf)/sizeof(TCHAR) - TAB_REPLACE_SIZE - 1)) { *p++ = _T(' '); } else { int len = lstrlen(p); TCHAR *c_out=(TCHAR*)p+TAB_REPLACE_SIZE+len; TCHAR *c_in=(TCHAR *)p+len; while (len-- > 0) { *c_out--=*c_in--; } lstrcpy(p, TAB_REPLACE); p += TAB_REPLACE_SIZE; *p = _T(' '); } } p = szUnusedBuf; // get the old left overs for (p2 = p; *p2;) { if (*p2 == _T('\r')) { *p2++ = 0; continue; } if (*p2 == _T('\n')) { *p2 = 0; while (!*p && p != p2) p++; LogMessage(p, bOEM); p = ++p2; continue; } p2 = CharNext(p2); } // If data was taken out from the unused buffer, move p contents to the start of szUnusedBuf if (p != szUnusedBuf) { TCHAR *p2 = szUnusedBuf; while (*p) *p2++ = *p++; *p2 = 0; } } } } else { if (g_to && GetTickCount() > dwLastOutput+g_to) { TerminateProcess(pi.hProcess, -1); lstrcpy(szRet, _T("timeout")); } else Sleep(LOOPTIMEOUT); } dwWait = WaitForSingleObject(pi.hProcess, 0); GetExitCodeProcess(pi.hProcess, &dwExit); PeekNamedPipe(read_stdout, 0, 0, 0, &dwRead, NULL); } done: if (log & 2) pushstring(szUnusedBuf); if (log & 1 && *szUnusedBuf) LogMessage(szUnusedBuf, bOEM); if ( dwExit == STATUS_ILLEGAL_INSTRUCTION ) lstrcpy(szRet, _T("error")); if (!szRet[0]) wsprintf(szRet,_T("%d"),dwExit); pushstring(szRet); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle(newstdout); CloseHandle(read_stdout); CloseHandle(newstdin); CloseHandle(read_stdin); if (pExec-2 >= g_exec) *(pExec-2) = _T('\0'); // skip space and quote if (executor) DeleteFile(executor); GlobalFree(g_exec); if (log) { GlobalUnlock(hUnusedBuf); GlobalFree(hUnusedBuf); } } }