<br>
LameXP is currently being developed using the following build environment:<br><ul>
<li><a href="http://www.microsoft.com/visualstudio/en-us" target="_blank">Visual Studio 2010</a> with Service Pack 1, running on Windows 7 with Service Pack 1
-<li>Desktop Qt v4.7.3 (MSVC 2008), included in <a href="http://qt.nokia.com/products/qt-sdk" target="_blank">Qt SDK v1.1</a>
+<li>Desktop Qt v4.8.0 (MSVC 2010), included in <a href="http://qt.nokia.com/products/qt-sdk" target="_blank">Qt SDK v1.2</a>
<li><a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=35AEDA01-421D-4BA5-B44B-543DC8C33A20" target="_blank">Windows Platform SDK v7.1</a> (Windows SDK for Windows 7 and .NET Framework 4)
-<li>The minimum supported Windows version is Windows XP with Service Pack 2</ul>
+<li>The minimum supported build platform is Windows XP with Service Pack 2</ul>
<br>
Also note the following hints:<br><ul>
<li>Run "qtenv2.bat" before launching Visual Studio in order to set up the Qt environment
<li>Visual Studio 2008 solution/project files are still provided for people targeting Windows 2000
<li>In order to make a "fully static" build of LameXP, you need to compile Qt as 'static' libraries
<li>The Windows Platform SDK v6.0A should work as well, but there may be a few limitations
+<li>Only the "fully static" builds may still run on Windows 2000, due to workarounds we implemented
<li>Support for the GNU Toolchain (GCC/MinGW + Make) is planned for a future version</ul>
<br>
In order to use the LameXP deployment scripts you need the following tools:<br><ul>
+<li>Visual Studio 2010 with Service Pack 1 with Desktop Qt v4.8.0
<li><a href="http://www.7-zip.org/" target="_blank">7-Zip</a> - file archiver with a high compression ratio
<li><a href="http://www.scratchpaper.com/" target="_blank">NSIS</a> - Nullsoft Scriptable Install System (Unicode Version)<ul>
<li><a href="http://nsis.sourceforge.net/StdUtils_plug-in" target="_blank">StdUtils plug-in</a>
<li><a href="http://upx.sourceforge.net/" target="_blank">UPX</a> - the Ultimate Packer for eXecutables
<li><a href="http://www.matcode.com/mpress.htm" target="_blank">MPRESS</a> - high-performance executable packer for PE32/PE32+
<li><a href="ftp://ftp.gnupg.org/gcrypt/binary/" target="_blank">GnuPG</a> - the GNU Privacy Guard v1.4.x<div style="height:7px"></div>
-<li>Copy 'buildenv.template.txt' to 'buildenv.txt' and edit the paths as needed!</ul>
+<li>NOTE: Copy 'buildenv.template.txt' to 'buildenv.txt' and edit the paths as needed!</ul>
<br>
Instructions to build Qt as 'static' libraries:<br><ul>
<li>Make sure Visual Studio 2010 and Strawberry Perl for Windows are installed
/*
* Static vars
*/
+quint64 AbstractTool::m_lastLaunchTime = 0ui64;
QMutex *AbstractTool::m_mutex_startProcess = NULL;
HANDLE AbstractTool::m_handle_jobObject = NULL;
+unsigned int AbstractTool::m_jobObjRefCount = 0U;
+
+/*
+ * Const
+ */
+static const DWORD START_DELAY = 333; //in milliseconds
+static const quint64 START_DELAY_NANO = START_DELAY * 1000 * 10; //in 100-nanosecond intervals
/*
* Constructor
m_mutex_startProcess = new QMutex();
}
- if(!m_handle_jobObject)
+ QMutexLocker lock(m_mutex_startProcess);
+
+ if(m_jobObjRefCount < 1U)
{
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
{
}
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
{
- m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
- if(m_handle_jobObject == INVALID_HANDLE_VALUE)
- {
- m_handle_jobObject = NULL;
- }
- if(m_handle_jobObject)
+ HANDLE jobObject = CreateJobObjectPtr(NULL, NULL);
+ if((jobObject != NULL) && (jobObject != INVALID_HANDLE_VALUE))
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+ memset(&jobExtendedLimitInfo.BasicLimitInformation, 0, sizeof(JOBOBJECT_BASIC_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));
+ if(SetInformationJobObjectPtr(jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
+ {
+ m_handle_jobObject = jobObject;
+ m_jobObjRefCount = 1U;
+ }
+ else
+ {
+ qWarning("Failed to set job object information!");
+ CloseHandle(jobObject);
+ }
}
}
}
+ else
+ {
+ m_jobObjRefCount++;
+ }
m_firstLaunch = true;
}
*/
AbstractTool::~AbstractTool(void)
{
- if(m_handle_jobObject)
+ QMutexLocker lock(m_mutex_startProcess);
+
+ if(m_jobObjRefCount >= 1U)
{
- CloseHandle(m_handle_jobObject);
- m_handle_jobObject = NULL;
+ m_jobObjRefCount--;
+ if((m_jobObjRefCount < 1U) && m_handle_jobObject)
+ {
+ CloseHandle(m_handle_jobObject);
+ m_handle_jobObject = NULL;
+ }
}
}
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
QMutexLocker lock(m_mutex_startProcess);
+
+ if(currentTime() <= m_lastLaunchTime)
+ {
+ Sleep(START_DELAY);
+ }
+
emit messageLogged(commandline2string(program, args) + "\n");
QProcessEnvironment env = process.processEnvironment();
if(process.waitForStarted())
{
-
- if(AssignProcessToJobObjectPtr)
+ if(AssignProcessToJobObjectPtr && m_handle_jobObject)
{
- AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
+ if(!AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess))
+ {
+ qWarning("Failed to assign process to job object!");
+ }
}
if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS))
{
m_firstLaunch = false;
}
+ m_lastLaunchTime = currentTime() + START_DELAY_NANO;
return true;
}
process.kill();
process.waitForFinished(-1);
+
+ m_lastLaunchTime = currentTime() + START_DELAY_NANO;
return false;
}
return (shortPath.isEmpty() ? longPath : shortPath);
}
+const quint64 AbstractTool::currentTime(void)
+{
+ FILETIME fileTime;
+ GetSystemTimeAsFileTime(&fileTime);
+
+ ULARGE_INTEGER temp;
+ temp.HighPart = fileTime.dwHighDateTime;
+ temp.LowPart = fileTime.dwLowDateTime;
+
+ return temp.QuadPart;
+}