/////////////////////////////////////////////////////////////////////////////// // LameXP - Audio Encoder Front-End // Copyright (C) 2004-2011 LoRd_MuldeR // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // http://www.gnu.org/licenses/gpl-2.0.txt /////////////////////////////////////////////////////////////////////////////// #include "Tool_Abstract.h" #include "Global.h" #include #include #include #include #include #include /* * Win32 API definitions */ typedef HANDLE (WINAPI *CreateJobObjectFun)(__in_opt LPSECURITY_ATTRIBUTES lpJobAttributes, __in_opt LPCSTR lpName); typedef BOOL (WINAPI *SetInformationJobObjectFun)(__in HANDLE hJob, __in JOBOBJECTINFOCLASS JobObjectInformationClass, __in_bcount(cbJobObjectInformationLength) LPVOID lpJobObjectInformation, __in DWORD cbJobObjectInformationLength); typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE hProcess); /* * Static vars */ QMutex *AbstractTool::m_mutex_startProcess = NULL; HANDLE AbstractTool::m_handle_jobObject = NULL; /* * Constructor */ AbstractTool::AbstractTool(void) { static CreateJobObjectFun CreateJobObjectPtr = NULL; static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL; if(!m_mutex_startProcess) { m_mutex_startProcess = new QMutex(); } if(!m_handle_jobObject) { if(!CreateJobObjectPtr || !SetInformationJobObjectPtr) { QLibrary Kernel32Lib("kernel32.dll"); CreateJobObjectPtr = (CreateJobObjectFun) Kernel32Lib.resolve("CreateJobObjectA"); SetInformationJobObjectPtr = (SetInformationJobObjectFun) Kernel32Lib.resolve("SetInformationJobObject"); } if(CreateJobObjectPtr && SetInformationJobObjectPtr) { m_handle_jobObject = CreateJobObjectPtr(NULL, NULL); if(m_handle_jobObject == INVALID_HANDLE_VALUE) { m_handle_jobObject = NULL; } if(m_handle_jobObject) { JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo; memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION; SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); } } } m_firstLaunch = true; } /* * Destructor */ AbstractTool::~AbstractTool(void) { } /* * Initialize and launch process object */ bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args) { static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL; QMutexLocker lock(m_mutex_startProcess); emit messageLogged(commandline2string(program, args) + "\n"); QProcessEnvironment env = process.processEnvironment(); if(env.isEmpty()) env = QProcessEnvironment::systemEnvironment(); env.insert("TEMP", QDir::toNativeSeparators(lamexp_temp_folder2())); env.insert("TMP", QDir::toNativeSeparators(lamexp_temp_folder2())); process.setProcessEnvironment(env); if(!AssignProcessToJobObjectPtr) { QLibrary Kernel32Lib("kernel32.dll"); AssignProcessToJobObjectPtr = (AssignProcessToJobObjectFun) Kernel32Lib.resolve("AssignProcessToJobObject"); } process.setProcessChannelMode(QProcess::MergedChannels); process.setReadChannel(QProcess::StandardOutput); process.start(program, args); if(process.waitForStarted()) { if(AssignProcessToJobObjectPtr) { AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess); } if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS)) { SetPriorityClass(process.pid()->hProcess, IDLE_PRIORITY_CLASS); } lock.unlock(); if(m_firstLaunch) { emit statusUpdated(0); m_firstLaunch = false; } return true; } emit messageLogged("Process creation has failed :-("); QString errorMsg= process.errorString().trimmed(); if(!errorMsg.isEmpty()) emit messageLogged(errorMsg); process.kill(); process.waitForFinished(-1); return false; } /* * Convert program arguments to single string */ QString AbstractTool::commandline2string(const QString &program, const QStringList &arguments) { QString commandline = (program.contains(' ') ? QString("\"%1\"").arg(program) : program); for(int i = 0; i < arguments.count(); i++) { commandline += (arguments.at(i).contains(' ') ? QString(" \"%1\"").arg(arguments.at(i)) : QString(" %1").arg(arguments.at(i))); } return commandline; } /* * Convert long path to short path */ QString AbstractTool::pathToShort(const QString &longPath) { QString shortPath; DWORD buffSize = GetShortPathNameW(reinterpret_cast(longPath.utf16()), NULL, NULL); if(buffSize > 0) { wchar_t *buffer = new wchar_t[buffSize]; DWORD result = GetShortPathNameW(reinterpret_cast(longPath.utf16()), buffer, buffSize); if(result > 0 && result < buffSize) { shortPath = QString::fromUtf16(reinterpret_cast(buffer)); } delete[] buffer; } return (shortPath.isEmpty() ? longPath : shortPath); }