Пример #1
0
HANDLE LaunchProcessLogon(char *domainaccount, char *password, char *cmd, char *env, char *map, char *dir, int priorityClass, int priority, HANDLE *hIn, HANDLE *hOut, HANDLE *hErr, int *pdwPid, int *nError, char *pszError, bool bDebug)
{
    HANDLE hStdin, hStdout, hStderr;
    HANDLE hPipeStdinR=NULL, hPipeStdinW=NULL;
    HANDLE hPipeStdoutR=NULL, hPipeStdoutW=NULL;
    HANDLE hPipeStderrR=NULL, hPipeStderrW=NULL;
    STARTUPINFO saInfo;
    PROCESS_INFORMATION psInfo;
    void *pEnv=NULL;
    char tSavedPath[MAX_PATH] = ".";
    HANDLE hRetVal = INVALID_HANDLE_VALUE;
    char account[100], domain[100] = "", *pszDomain = NULL;
    HANDLE hUser;
    int num_tries;
    int error;
    DWORD launch_flag;
    
    // Launching of the client processes must be synchronized because
    // stdin,out,err are redirected for the entire process, not just this thread.
    WaitForSingleObject(g_hLaunchMutex, INFINITE);
    
    // Don't handle errors, just let the process die.
    // In the future this will be configurable to allow various debugging options.
#ifdef USE_SET_ERROR_MODE
    DWORD dwOriginalErrorMode;
    dwOriginalErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
#endif
    
    // Save stdin, stdout, and stderr
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    hStderr = GetStdHandle(STD_ERROR_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE  || hStderr == INVALID_HANDLE_VALUE)
    {
	*nError = GetLastError();
	strcpy(pszError, "GetStdHandle failed, ");
	ReleaseMutex(g_hLaunchMutex);
#ifdef USE_SET_ERROR_MODE
	SetErrorMode(dwOriginalErrorMode);
#endif
	return INVALID_HANDLE_VALUE;
    }
    
    // Set the security attributes to allow handles to be inherited
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.lpSecurityDescriptor = NULL;
    saAttr.bInheritHandle = TRUE;
    
    // Create pipes for stdin, stdout, and stderr
    if (!CreatePipe(&hPipeStdinR, &hPipeStdinW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    if (!CreatePipe(&hPipeStdoutR, &hPipeStdoutW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    if (!CreatePipe(&hPipeStderrR, &hPipeStderrW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    
    // Make the ends of the pipes that this process will use not inheritable
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStdinW, GetCurrentProcess(), hIn, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	goto CLEANUP;
    }
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStdoutR, GetCurrentProcess(), hOut, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	CloseHandle(*hIn);
	goto CLEANUP;
    }
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStderrR, GetCurrentProcess(), hErr, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	CloseHandle(*hIn);
	CloseHandle(*hOut);
	goto CLEANUP;
    }
    
    // Set stdin, stdout, and stderr to the ends of the pipe the created process will use
    if (!SetStdHandle(STD_INPUT_HANDLE, hPipeStdinR))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	CloseHandle(*hIn);
	CloseHandle(*hOut);
	CloseHandle(*hErr);
	goto CLEANUP;
    }
    if (!SetStdHandle(STD_OUTPUT_HANDLE, hPipeStdoutW))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	CloseHandle(*hIn);
	CloseHandle(*hOut);
	CloseHandle(*hErr);
	goto RESTORE_CLEANUP;
    }
    if (!SetStdHandle(STD_ERROR_HANDLE, hPipeStderrW))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	CloseHandle(*hIn);
	CloseHandle(*hOut);
	CloseHandle(*hErr);
	goto RESTORE_CLEANUP;
    }
    
    // Create the process
    memset(&saInfo, 0, sizeof(STARTUPINFO));
    saInfo.cb         = sizeof(STARTUPINFO);
    saInfo.hStdInput  = hPipeStdinR;
    saInfo.hStdOutput = hPipeStdoutW;
    saInfo.hStdError  = hPipeStderrW;
    saInfo.dwFlags    = STARTF_USESTDHANDLES;
    //saInfo.lpDesktop = "WinSta0\\Default";
    //saInfo.wShowWindow = SW_SHOW;
    
    SetEnvironmentVariables(env);
    pEnv = GetEnvironmentStrings();
    
    ParseAccountDomain(domainaccount, account, domain);
    if (strlen(domain) < 1)
	pszDomain = NULL;
    else
	pszDomain = domain;

    hUser = GetUserHandle(account, pszDomain, password, nError);
    if (hUser == INVALID_HANDLE_VALUE)
    {
	strcpy(pszError, "LogonUser failed, ");
	FreeEnvironmentStrings((TCHAR*)pEnv);
	SetCurrentDirectory(tSavedPath);
	RemoveEnvironmentVariables(env);
	CloseHandle(*hIn);
	CloseHandle(*hOut);
	CloseHandle(*hErr);
	goto RESTORE_CLEANUP;
    }

    if (ImpersonateLoggedOnUser(hUser))
    {
	if (!MapUserDrives(map, domainaccount, password, pszError))
	{
	    err_printf("LaunchProcessLogon:MapUserDrives(%s, %s) failed, %s", map, domainaccount, pszError);
	}

	GetCurrentDirectory(MAX_PATH, tSavedPath);
	SetCurrentDirectory(dir);

	launch_flag = 
	    //DETACHED_PROCESS | IDLE_PRIORITY_CLASS;
	    //CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS;
	    //CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS;
	    //CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP;
	    //DETACHED_PROCESS | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP;
	    //CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_SUSPENDED;
	    CREATE_SUSPENDED | CREATE_NO_WINDOW | priorityClass;
	if (bDebug)
	    launch_flag = launch_flag | DEBUG_PROCESS;

#ifdef USE_WINDOW_STATIONS
	AttachToWorkstation();
#endif

	/*PrintPriorities(priorityClass, priority);*/
	num_tries = 4;
	do
	{
	    if (CreateProcessAsUser(
		hUser,
		NULL,
		cmd,
		NULL, NULL, TRUE,
		launch_flag,
		pEnv,
		NULL,
		&saInfo, &psInfo))
	    {
		SetThreadPriority(psInfo.hThread, priority);

                DWORD dwClass, dwPriority;
		dwClass = GetPriorityClass(psInfo.hProcess);
		dwPriority = GetThreadPriority(psInfo.hThread);
		PrintPriorities(dwClass, dwPriority);

		ResumeThread(psInfo.hThread);
		hRetVal = psInfo.hProcess;
		*pdwPid = psInfo.dwProcessId;

		CloseHandle(psInfo.hThread);
		num_tries = 0;
	    }
	    else
	    {
		error = GetLastError();
		if (error == ERROR_REQ_NOT_ACCEP)
		{
		    Sleep(1000);
		    num_tries--;
		    if (num_tries == 0)
		    {
			*nError = error;
			strcpy(pszError, "CreateProcessAsUser failed, ");
		    }
		}
		else
		{
		    *nError = error;
		    strcpy(pszError, "CreateProcessAsUser failed, ");
		    num_tries = 0;
		}
	    }
	} while (num_tries);
	//RevertToSelf(); // If you call RevertToSelf, the network mapping goes away.
#ifdef USE_WINDOW_STATIONS
	DetachFromWorkstation();
#endif
    }
    else
    {
	*nError = GetLastError();
	strcpy(pszError, "ImpersonateLoggedOnUser failed, ");
    }
    
    FreeEnvironmentStrings((TCHAR*)pEnv);
    SetCurrentDirectory(tSavedPath);
    RemoveEnvironmentVariables(env);
    
RESTORE_CLEANUP:
    // Restore stdin, stdout, stderr
    SetStdHandle(STD_INPUT_HANDLE, hStdin);
    SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
    SetStdHandle(STD_ERROR_HANDLE, hStderr);
    
CLEANUP:
    ReleaseMutex(g_hLaunchMutex);
    CloseHandle(hPipeStdinR);
    CloseHandle(hPipeStdoutW);
    CloseHandle(hPipeStderrW);

#ifdef USE_SET_ERROR_MODE
    SetErrorMode(dwOriginalErrorMode);
#endif

    return hRetVal;
}
Пример #2
0
// Function name	: LaunchProcess
// Description	    : 
// Return type		: HANDLE 
HANDLE LaunchProcess(char *cmd, char *env, char *dir, int priorityClass, int priority, HANDLE *hIn, HANDLE *hOut, HANDLE *hErr, int *pdwPid, int *nError, char *pszError, bool bDebug)
{
    HANDLE hStdin, hStdout, hStderr;
    HANDLE hPipeStdinR=NULL, hPipeStdinW=NULL;
    HANDLE hPipeStdoutR=NULL, hPipeStdoutW=NULL;
    HANDLE hPipeStderrR=NULL, hPipeStderrW=NULL;
    STARTUPINFO saInfo;
    PROCESS_INFORMATION psInfo;
    void *pEnv=NULL;
    char tSavedPath[MAX_PATH] = ".";
    HANDLE hRetVal = INVALID_HANDLE_VALUE;
    DWORD launch_flag;
    
    // Launching of the client processes must be synchronized because
    // stdin,out,err are redirected for the entire process, not just this thread.
    WaitForSingleObject(g_hLaunchMutex, INFINITE);
    
    // Don't handle errors, just let the process die.
    // In the future this will be configurable to allow various debugging options.
#ifdef USE_SET_ERROR_MODE
    DWORD dwOriginalErrorMode;
    dwOriginalErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
#endif
    
    // Save stdin, stdout, and stderr
    hStdin = GetStdHandle(STD_INPUT_HANDLE);
    hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    hStderr = GetStdHandle(STD_ERROR_HANDLE);
    if (hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE  || hStderr == INVALID_HANDLE_VALUE)
    {
	*nError = GetLastError();
	strcpy(pszError, "GetStdHandle failed, ");
	ReleaseMutex(g_hLaunchMutex);
	return INVALID_HANDLE_VALUE;
    }
    
    // Set the security attributes to allow handles to be inherited
    SECURITY_ATTRIBUTES saAttr;
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    saAttr.lpSecurityDescriptor = NULL;
    saAttr.bInheritHandle = TRUE;
    
    // Create pipes for stdin, stdout, and stderr
    if (!CreatePipe(&hPipeStdinR, &hPipeStdinW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    if (!CreatePipe(&hPipeStdoutR, &hPipeStdoutW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    if (!CreatePipe(&hPipeStderrR, &hPipeStderrW, &saAttr, 0))
    {
	*nError = GetLastError();
	strcpy(pszError, "CreatePipe failed, ");
	goto CLEANUP;
    }
    
    // Make the ends of the pipes that this process will use not inheritable
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStdinW, GetCurrentProcess(), hIn, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	goto CLEANUP;
    }
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStdoutR, GetCurrentProcess(), hOut, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	goto CLEANUP;
    }
    if (!DuplicateHandle(GetCurrentProcess(), hPipeStderrR, GetCurrentProcess(), hErr, 
	0, FALSE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
    {
	*nError = GetLastError();
	strcpy(pszError, "DuplicateHandle failed, ");
	goto CLEANUP;
    }
    
    // Set stdin, stdout, and stderr to the ends of the pipe the created process will use
    if (!SetStdHandle(STD_INPUT_HANDLE, hPipeStdinR))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	goto CLEANUP;
    }
    if (!SetStdHandle(STD_OUTPUT_HANDLE, hPipeStdoutW))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	goto RESTORE_CLEANUP;
    }
    if (!SetStdHandle(STD_ERROR_HANDLE, hPipeStderrW))
    {
	*nError = GetLastError();
	strcpy(pszError, "SetStdHandle failed, ");
	goto RESTORE_CLEANUP;
    }
    
    // Create the process
    memset(&saInfo, 0, sizeof(STARTUPINFO));
    saInfo.cb = sizeof(STARTUPINFO);
    saInfo.hStdError = hPipeStderrW;
    saInfo.hStdInput = hPipeStdinR;
    saInfo.hStdOutput = hPipeStdoutW;
    saInfo.dwFlags = STARTF_USESTDHANDLES;
    //saInfo.lpDesktop = "WinSta0\\Default";
    //saInfo.wShowWindow = SW_SHOW;
    
    SetEnvironmentVariables(env);
    pEnv = GetEnvironmentStrings();
    
    GetCurrentDirectory(MAX_PATH, tSavedPath);
    SetCurrentDirectory(dir);
    
    launch_flag = 
	//DETACHED_PROCESS | IDLE_PRIORITY_CLASS;
	//CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS;
	//CREATE_NO_WINDOW | BELOW_NORMAL_PRIORITY_CLASS;
	//CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP;
	//DETACHED_PROCESS | IDLE_PRIORITY_CLASS | CREATE_NEW_PROCESS_GROUP;
	//CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS | CREATE_SUSPENDED;
	CREATE_SUSPENDED | CREATE_NO_WINDOW | priorityClass;
    if (bDebug)
	launch_flag = launch_flag | DEBUG_PROCESS;

    /*PrintPriorities(priorityClass, priority);*/
    if (CreateProcess(
	NULL,
	cmd,
	NULL, NULL, TRUE,
	launch_flag,
	pEnv,
	NULL,
	&saInfo, &psInfo))
    {
	SetThreadPriority(psInfo.hThread, priority);

	DWORD dwClass, dwPriority;
	dwClass = GetPriorityClass(psInfo.hProcess);
	dwPriority = GetThreadPriority(psInfo.hThread);
	PrintPriorities(dwClass, dwPriority);

	ResumeThread(psInfo.hThread);
	hRetVal = psInfo.hProcess;
	*pdwPid = psInfo.dwProcessId;

	CloseHandle(psInfo.hThread);
    }
    else
    {
	*nError = GetLastError();
	strcpy(pszError, "CreateProcess failed, ");
    }
    
    FreeEnvironmentStrings((TCHAR*)pEnv);
    SetCurrentDirectory(tSavedPath);
    RemoveEnvironmentVariables(env);
    
RESTORE_CLEANUP:
    // Restore stdin, stdout, stderr
    SetStdHandle(STD_INPUT_HANDLE, hStdin);
    SetStdHandle(STD_OUTPUT_HANDLE, hStdout);
    SetStdHandle(STD_ERROR_HANDLE, hStderr);
    
CLEANUP:
    ReleaseMutex(g_hLaunchMutex);
    CloseHandle(hPipeStdinR);
    CloseHandle(hPipeStdoutW);
    CloseHandle(hPipeStderrW);
    
#ifdef USE_SET_ERROR_MODE
    SetErrorMode(dwOriginalErrorMode);
#endif

    return hRetVal;
}
Пример #3
0
//--------------------------------------------------------------------------------------------------
static inline le_result_t StartProc
(
    proc_Ref_t procRef,             ///< [IN] The process to start.
    const char* workingDirPtr,      ///< [IN] The path to the process's working directory, relative
                                    ///       to the sandbox directory.
    uid_t uid,                      ///< [IN] The user ID to start the process as.
    gid_t gid,                      ///< [IN] The primary group ID for this process.
    const gid_t* groupsPtr,         ///< [IN] List of supplementary groups for this process.
    size_t numGroups,               ///< [IN] The number of groups in the supplementary groups list.
    const char* sandboxDirPtr       ///< [IN] The path to the root of the sandbox this process is to
                                    ///       run in.  If NULL then process will be unsandboxed.
)
{
    if (procRef->pid != -1)
    {
        LE_ERROR("Process '%s' (PID: %d) cannot be started because it is already running.",
                 procRef->name, procRef->pid);
        return LE_FAULT;
    }

    // Create a pipe for parent/child synchronization.
    int syncPipeFd[2];
    LE_FATAL_IF(pipe(syncPipeFd) == -1, "Could not create synchronization pipe.  %m.");

    // @Note The current IPC system does not support forking so any reads to the config DB must be
    //       done in the parent process.

    // Get the environment variables from the config tree for this process.
    EnvVar_t envVars[LIMIT_MAX_NUM_ENV_VARS];
    int numEnvVars = GetEnvironmentVariables(procRef, envVars, LIMIT_MAX_NUM_ENV_VARS);

    if (numEnvVars == LE_FAULT)
    {
        LE_ERROR("Error getting environment variables.  Process '%s' cannot be started.",
                 procRef->name);
        return LE_FAULT;
    }

    // Get the command line arguments from the config tree for this process.
    char argsBuffers[LIMIT_MAX_NUM_CMD_LINE_ARGS][LIMIT_MAX_ARGS_STR_BYTES];
    char* argsPtr[NUM_ARGS_PTRS];

    if (GetArgs(procRef, argsBuffers, argsPtr) != LE_OK)
    {
        LE_ERROR("Could not get command line arguments, process '%s' cannot be started.",
                 procRef->name);
        return LE_FAULT;
    }

    // Get the smack label for the process.
    // Must get the label here because smack_GetAppLabel uses the config and we can not
    // use any IPC after a fork.
    char smackLabel[LIMIT_MAX_SMACK_LABEL_BYTES];
    appSmack_GetLabel(app_GetName(procRef->appRef), smackLabel, sizeof(smackLabel));

    // Create pipes for the process's standard error and standard out streams.
    int stderrPipe[2];
    int stdoutPipe[2];
    CreatePipe(procRef, stderrPipe, STDERR_FILENO);
    CreatePipe(procRef, stdoutPipe, STDOUT_FILENO);

    // Create the child process
    pid_t pID = fork();

    if (pID < 0)
    {
        LE_EMERG("Failed to fork.  %m.");
        return LE_FAULT;
    }

    if (pID == 0)
    {
        // Wait for the parent to allow us to continue by blocking on the read pipe until it
        // is closed.
        fd_Close(syncPipeFd[WRITE_PIPE]);

        ssize_t numBytesRead;
        int dummyBuf;
        do
        {
            numBytesRead = read(syncPipeFd[READ_PIPE], &dummyBuf, 1);
        }
        while ( ((numBytesRead == -1)  && (errno == EINTR)) || (numBytesRead != 0) );

        LE_FATAL_IF(numBytesRead == -1, "Could not read synchronization pipe.  %m.");

        // The parent has allowed us to continue.

        // Redirect the process's standard streams.
        RedirectStdStream(stderrPipe, STDERR_FILENO);
        RedirectStdStream(stdoutPipe, STDOUT_FILENO);

        // Set the process's SMACK label.
        smack_SetMyLabel(smackLabel);

        // Set the umask so that files are not accidentally created with global permissions.
        umask(S_IRWXG | S_IRWXO);

        // Unblock all signals that might have been blocked.
        sigset_t sigSet;
        LE_ASSERT(sigfillset(&sigSet) == 0);
        LE_ASSERT(pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL) == 0);

        SetEnvironmentVariables(envVars, numEnvVars);

        // Setup the process environment.
        if (sandboxDirPtr != NULL)
        {
            // Sandbox the process.
            sandbox_ConfineProc(sandboxDirPtr, uid, gid, groupsPtr, numGroups, workingDirPtr);
        }
        else
        {
            ConfigNonSandboxedProcess(workingDirPtr);
        }

        // Launch the child program.  This should not return unless there was an error.
        LE_INFO("Execing '%s'", argsPtr[0]);

        // Close all non-standard file descriptors.
        fd_CloseAllNonStd();

        execvp(argsPtr[0], &(argsPtr[1]));

        // The program could not be started.  Log an error message.
        log_ReInit();
        LE_FATAL("Could not exec '%s'.  %m.", argsPtr[0]);
    }

    procRef->pid = pID;
    procRef->paused = false;

    // Don't need this end of the pipe.
    fd_Close(syncPipeFd[READ_PIPE]);

    // Set the scheduling priority for the child process while the child process is blocked.
    SetSchedulingPriority(procRef);

    // Send standard pipes to the log daemon so they will show up in the logs.
    SendStdPipeToLogDaemon(procRef, stderrPipe, STDERR_FILENO);
    SendStdPipeToLogDaemon(procRef, stdoutPipe, STDOUT_FILENO);

    // Set the resource limits for the child process while the child process is blocked.
    if (resLim_SetProcLimits(procRef) != LE_OK)
    {
        LE_ERROR("Could not set the resource limits.  %m.");

        kill_Hard(procRef->pid);
    }

    LE_INFO("Starting process %s with pid %d", procRef->name, procRef->pid);

    // Unblock the child process.
    fd_Close(syncPipeFd[WRITE_PIPE]);

    return LE_OK;
}
Пример #4
0
void
SessionImpl::Initialize (/*[in]*/ const Session::InitInfo & initInfo)
{
  string val;

  PathName programInvocationName = initInfo.GetProgramInvocationName();
  programInvocationName = programInvocationName.GetFileNameWithoutExtension();
  const char * lpsz = strstr(programInvocationName.Get(), MIKTEX_ADMIN_SUFFIX);
  bool forceAdminMode =
    (lpsz != 0 && strlen(lpsz) == strlen(MIKTEX_ADMIN_SUFFIX));

#if defined(MIKTEX_WINDOWS)
  if (! forceAdminMode)
  {
    programInvocationName =
      GetMyProgramFile(false).Normalize().GetFileNameWithoutExtension().Get();
    lpsz = strstr(programInvocationName.Get(), MIKTEX_ADMIN_SUFFIX);
    forceAdminMode =
      (lpsz != 0 && strlen(lpsz) == strlen(MIKTEX_ADMIN_SUFFIX));      
  }
#endif

  bool oldAdminMode = adminMode;

  if (forceAdminMode)
  {
    adminMode = true;
  }
  else
  {
    adminMode = ((initInfo.GetFlags() & InitFlags::AdminMode) != 0);
  }

#if defined(_MSC_VER)
  if (Utils::GetEnvironmentString("MIKTEX_DEBUG_ON_STD_EXCEPTION", val))
    {
      debugOnStdException = atoi(val.c_str());
    }
#endif

  // check minimum system requirements (which is Windows 2000 atm)
#if defined(MIKTEX_WINDOWS) && ! defined(MIKTEX_SUPPORT_LEGACY_WINDOWS)
  DWORD version = GetVersion();
  bool nt = version < 0x80000000;
  DWORD major = LOBYTE(LOWORD(version));
  DWORD minor = HIBYTE(LOWORD(version));
  if ((! nt)			// Windows 9x/Me
      || (major < 5))		// Windows NT 3.x/4.x
    {
      string msg = T_("Unsupported operation system version (");
      if (nt)
	{
	  msg += "NT ";
	}
      msg += NUMTOSTR(major);
      msg += ".";
      msg += NUMTOSTR(minor);
      msg += ").";
      FATAL_MIKTEX_ERROR ("SessionImpl::Initialize",
			  msg.c_str(),
			  0);
    }
#endif

  if (initInfo.GetSizeOfStruct() != sizeof(initInfo))
    {
      INVALID_ARGUMENT ("SessionImpl::Initialize", 0);
    }

#if defined(MIKTEX_WINDOWS)
  if ((initInfo.GetFlags() & InitFlags::InitializeCOM) != 0)
    {
      MyCoInitialize ();
    }
#endif

  Botan::LibraryInitializer::initialize ();

  initialized = true;

  this->initInfo = initInfo;

  theNameOfTheGame = initInfo.GetTheNameOfTheGame();

  RegisterLibraryTraceStreams ();

  // enable trace streams
  string traceOptions;
  traceOptions = initInfo.GetTraceFlags();
  if (traceOptions.empty())
    {
      Utils::GetEnvironmentString (MIKTEX_ENV_TRACE, traceOptions);
    }
#if defined(MIKTEX_WINDOWS)
  if (traceOptions.empty()
      && (initInfo.GetFlags() & InitFlags::NoConfigFiles) == 0)
    {
      if (! winRegistry::TryGetRegistryValue(TriState::False,
					     MIKTEX_REGKEY_CORE,
					     MIKTEX_REGVAL_TRACE,
					     traceOptions,
					     0))
	{
	  traceOptions = "";
	}
    }
#endif
  if (! traceOptions.empty())
    {
      TraceStream::SetTraceFlags (traceOptions.c_str());
    }

  if (! forceAdminMode)
  {
    adminMode = oldAdminMode;
    SetAdminMode ((initInfo.GetFlags() & InitFlags::AdminMode) != 0);
  }

  DoStartupConfig ();

  InitializeRootDirectories ();

  Utils::GetEnvironmentString (MIKTEX_ENV_PACKAGE_LIST_FILE,
			       packageHistoryFile);

  PushAppName (Utils::GetExeName().c_str());
  
  // the process start directory is the initial scratch directory
  scratchDirectories.push_back (PathName().SetToCurrentDirectory());

  string miktexCwd;
  if (Utils::GetEnvironmentString(MIKTEX_ENV_CWD_LIST, miktexCwd))
    {
      for (CSVList cwd (miktexCwd.c_str(), PATH_DELIMITER);
	   cwd.GetCurrent() != 0;
	   ++ cwd)
	{
	  AddInputDirectory (cwd.GetCurrent(), true);
	}
    }
  
  SetEnvironmentVariables ();

  trace_core->WriteFormattedLine
    ("core",
     T_("initializing MiKTeX core library version %s"),
     MIKTEX_COMPONENT_VERSION_STR);

#if defined(MIKTEX_WINDOWS) && defined(MIKTEX_CORE_SHARED)
  if (dynamicLoad.Get() == TriState::True)
    {
      trace_core->WriteFormattedLine ("core", T_("dynamic load"));
    }
#endif
  
  trace_core->WriteFormattedLine ("core",
				  T_("operating system: %s"),
				  Utils::GetOSVersionString().c_str());
  
  trace_core->WriteFormattedLine ("core",
				  T_("program file: %s"),
				  GetMyProgramFile(true).Get());

  trace_config->WriteFormattedLine ("core",
				    T_("session locale: %s"),
				    defaultLocale.name().c_str());
  
}
Пример #5
0
// Function name	: RunLocal
// Description	    : 
// Return type		: void 
// Argument         : bool bDoSMP
void RunLocal(bool bDoSMP)
{
	DWORD size = 100;
	TCHAR pszHost[100], pszCmdLine[MAX_PATH], error_msg[256], pszEnv[256], pszExtra[MAX_PATH];
	STARTUPINFO saInfo;
	PROCESS_INFORMATION psInfo;
	LPTSTR pEnv;
	int rootPort=0;
	HANDLE *hProcess = new HANDLE[g_nHosts];
			
	GetComputerName(pszHost, &size);

	wsprintf(pszCmdLine, TEXT("%s %s"), g_pszExe, g_pszArgs);

	GetTempFileName(_T("."), _T("mpi"), 0, pszExtra);
	// This produces a name in the form: ".\XXXmpi.tmp"
	// \ is illegal in named objects so use &pszExtra[2] instead of pszExtra for the JobID
	if (bDoSMP)
	{
		wsprintf(pszEnv, _T("MPICH_JOBID=%s|MPICH_IPROC=0|MPICH_NPROC=%d|MPICH_ROOTHOST=%s|MPICH_ROOTPORT=%d|MPICH_EXTRA=%s|MPICH_COMNIC=%s|MPICH_SHM_LOW=0|MPICH_SHM_HIGH=%d"),
				&pszExtra[2], g_nHosts, pszHost, -1, pszExtra, pszHost, g_nHosts-1);
	}
	else
	{
		wsprintf(pszEnv, _T("MPICH_JOBID=%s|MPICH_IPROC=0|MPICH_NPROC=%d|MPICH_ROOTHOST=%s|MPICH_ROOTPORT=%d|MPICH_EXTRA=%s|MPICH_COMNIC=%s"),
				&pszExtra[2], g_nHosts, pszHost, -1, pszExtra, pszHost);
	}

	SetEnvironmentVariables(pszEnv);
	if (_tcslen(g_pszEnv) > 0)
		SetEnvironmentVariables(g_pszEnv);
	pEnv = GetEnvironmentStrings();

	GetStartupInfo(&saInfo);

	// launch first process
	if (CreateProcess(
		NULL,
		pszCmdLine,
		NULL, NULL, FALSE,
		IDLE_PRIORITY_CLASS, 
		pEnv,
		NULL,
		&saInfo, &psInfo))
	{
		hProcess[0] = psInfo.hProcess;
		CloseHandle(psInfo.hThread);
	}
	else
	{
		int error = GetLastError();
		Translate_Error(error, error_msg, TEXT("CreateProcess failed: "));
		_tprintf(TEXT("Unable to launch '%s', error %d: %s"), pszCmdLine, error, error_msg);
		return;
	}

	RemoveEnvironmentVariables(pszEnv);
	FreeEnvironmentStrings(pEnv);

	if (g_bNoMPI)
	{
		rootPort = -1;
	}
	else
	{
		// Open the file and read the port number written by the first process
		HANDLE hFile = CreateFile(pszExtra, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
		{
			Translate_Error(GetLastError(), error_msg, TEXT("CreateFile failed "));
			_tprintf(error_msg);
			return;
		}
		
		DWORD num_read = 0;
		TCHAR pBuffer[100];
		pBuffer[0] = '\0';
		TCHAR *pChar = pBuffer;
		clock_t cStart = clock();
		while (true)
		{
			num_read = 0;
			if (!ReadFile(hFile, pChar, 100, &num_read, NULL))
			{
				Translate_Error(GetLastError(), error_msg, TEXT("ReadFile failed "));
				_tprintf(error_msg);
				return;
			}
			if (num_read == 0)
			{
				if (clock() - cStart > 10 * CLOCKS_PER_SEC)
				{
					_tprintf(TEXT("Wait for process 0 to write port to temporary file timed out\n"));
					TerminateProcess(hProcess, 0);
					return;
				}
				Sleep(100);
			}
			else
			{
				for (int i=0; i<(int)num_read; i++)
				{
					if (*pChar == _T('\n'))
						break;
					pChar ++;
				}
				if (*pChar == _T('\n'))
					break;
			}
		}
		CloseHandle(hFile);
		rootPort = _ttoi(pBuffer);
	}
	DeleteFile(pszExtra);

	// launch all the rest of the processes
	for (int i=1; i<g_nHosts; i++)
	{
		if (bDoSMP)
		{
			wsprintf(pszEnv, _T("MPICH_JOBID=%s|MPICH_IPROC=%d|MPICH_NPROC=%d|MPICH_ROOTHOST=%s|MPICH_ROOTPORT=%d|MPICH_COMNIC=%s|MPICH_SHM_LOW=0|MPICH_SHM_HIGH=%d"),
				&pszExtra[2], i, g_nHosts, pszHost, rootPort, pszHost, g_nHosts-1);
		}
		else
		{
			wsprintf(pszEnv, _T("MPICH_JOBID=%s|MPICH_IPROC=%d|MPICH_NPROC=%d|MPICH_ROOTHOST=%s|MPICH_ROOTPORT=%d|MPICH_COMNIC=%s"),
				&pszExtra[2], i, g_nHosts, pszHost, rootPort, pszHost);
		}
		
		SetEnvironmentVariables(pszEnv);
		pEnv = GetEnvironmentStrings();
		
		if (CreateProcess(
			NULL,
			pszCmdLine,
			NULL, NULL, FALSE,
			IDLE_PRIORITY_CLASS, 
			pEnv,
			NULL,
			&saInfo, &psInfo))
		{
			hProcess[i] = psInfo.hProcess;
			CloseHandle(psInfo.hThread);
		}
		else
		{
			int error = GetLastError();
			Translate_Error(error, error_msg, TEXT("CreateProcess failed: "));
			_tprintf(TEXT("Unable to launch '%s', error %d: %s"), pszCmdLine, error, error_msg);
			return;
		}
		
		RemoveEnvironmentVariables(pszEnv);
		FreeEnvironmentStrings(pEnv);
	}

	// Wait for all the processes to terminate
	WaitForLotsOfObjects(g_nHosts, hProcess);

	for (i=0; i<g_nHosts; i++)
		CloseHandle(hProcess[i]);
	delete hProcess;
}