Пример #1
0
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 );
}
Пример #2
0
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);
    }
  }
}
Пример #3
0
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);
    }
  }
}