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; }
// 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; }
//-------------------------------------------------------------------------------------------------- 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; }
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()); }
// 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; }