void executeCommand()

in src/main/cpp/launcher/windows/src/ProcessUtils.c [111:217]


void executeCommand(LauncherProperties * props, WCHAR * command, WCHAR * dir, DWORD timeLimitMillis, HANDLE hWriteOutput, HANDLE hWriteError, DWORD priority) {
    STARTUPINFOW si;
    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;
    PROCESS_INFORMATION pi;
    
    HANDLE newProcessInput;
    HANDLE newProcessOutput;
    HANDLE newProcessError;
    
    HANDLE currentProcessStdout;
    HANDLE currentProcessStdin;
    HANDLE currentProcessStderr;
    
    WCHAR * directory;
    
    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
    sa.lpSecurityDescriptor = &sd;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    
    
    if (!CreatePipe(&newProcessInput, &currentProcessStdin, &sa, 0)) {
        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for input. ", NULL , GetLastError());
        props->status = ERROR_ON_EXECUTE_PROCESS;
        return;
    }
    
    if (!CreatePipe(&currentProcessStdout, &newProcessOutput, &sa, 0)) {
        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for output. ", NULL , GetLastError());
        CloseHandle(newProcessInput);
        CloseHandle(currentProcessStdin);
        props->status = ERROR_ON_EXECUTE_PROCESS;
        return;
    }
    
    if (!CreatePipe(&currentProcessStderr, &newProcessError, &sa, 0)) {
        writeErrorA(props, OUTPUT_LEVEL_NORMAL, 1, "Can`t create pipe for error. ", NULL , GetLastError());
        CloseHandle(newProcessInput);
        CloseHandle(currentProcessStdin);
        CloseHandle(newProcessOutput);
        CloseHandle(currentProcessStdout);
        props->status = ERROR_ON_EXECUTE_PROCESS;
        return;
    }
    
    
    GetStartupInfoW(&si);
    
    si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;
    si.hStdOutput = newProcessOutput;
    si.hStdError = newProcessError;
    si.hStdInput = newProcessInput;
    
    directory = (dir!=NULL) ? dir : getCurrentDirectory();
    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "Create new process: ", 1);
    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "          command : ", 0);
    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, command, 1);
    writeMessageA(props, OUTPUT_LEVEL_NORMAL, 0, "        directory : ", 0);
    writeMessageW(props, OUTPUT_LEVEL_NORMAL, 0, directory, 1);
    
    props->exitCode = ERROR_OK;
    if (CreateProcessW(NULL, command, NULL, NULL, TRUE,
    CREATE_NEW_CONSOLE | CREATE_NO_WINDOW | CREATE_DEFAULT_ERROR_MODE | priority,
    NULL, directory, &si, &pi)) {        
        // TODO
        // Check whether volder virtualization can brake things and provide method to disable it if necessary 
        // I am not sure whether we need it off or on.
        // http://www.netbeans.org/issues/show_bug.cgi?id=122186
        DWORD timeOut = ((timeLimitMillis<=0) ? DEFAULT_PROCESS_TIMEOUT: timeLimitMillis);
        props->status = ERROR_OK;
        writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... process created", 1);
        
        props->exitCode = readProcessStream(pi, currentProcessStdin, currentProcessStdout, currentProcessStderr, timeOut, newProcessInput, hWriteOutput, hWriteError);
        
        if(props->exitCode==STILL_ACTIVE) {
            //actually we have reached the timeout of the process and need to terminate it
            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... process is timeouted", 1);
            GetExitCodeProcess(pi.hProcess, & (props->exitCode));
            
            if(props->exitCode==STILL_ACTIVE) {
                TerminateProcess(pi.hProcess, 0);
                writeMessageA(props, OUTPUT_LEVEL_DEBUG, 1, "... terminate process", 1);
                //Terminating process...It worked too much without any stdout/stdin/stderr
                props->status = ERROR_PROCESS_TIMEOUT;//terminated by timeout                
            }
        } else {
            //application finished its work... succesfully or not - it doesn`t matter            
            writeMessageA(props, OUTPUT_LEVEL_DEBUG, 0, "... process finished his work", 1);
        }
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }  else {
        writeErrorA(props, OUTPUT_LEVEL_DEBUG, 1, "... can`t create process.", NULL, GetLastError());
        props->status = ERROR_ON_EXECUTE_PROCESS;        
    }
    
    
    CloseHandle(newProcessInput);
    CloseHandle(newProcessOutput);
    CloseHandle(newProcessError);
    CloseHandle(currentProcessStdin);
    CloseHandle(currentProcessStdout);
    CloseHandle(currentProcessStderr);    
}