static const unsigned int g_lamexp_toolver_coreaudio = VER_LAMEXP_TOOL_COREAUDIO;
//Special folders
-static QString g_lamexp_temp_folder;
+static struct
+{
+ QString temp;
+ QString knownFolders[3];
+ QReadWriteLock lock;
+}
+g_lamexp_folder;
//Tools
-static QMap<QString, LockedFile*> g_lamexp_tool_registry;
-static QMap<QString, unsigned int> g_lamexp_tool_versions;
-static QReadWriteLock g_lamexp_tool_lock;
+static struct
+{
+ QMap<QString, LockedFile*> registry;
+ QMap<QString, unsigned int> versions;
+ QReadWriteLock lock;
+}
+g_lamexp_tools;
//Languages
static struct
QMap<QString, QString> names;
QMap<QString, unsigned int> sysid;
QMap<QString, unsigned int> cntry;
+ QReadWriteLock lock;
}
g_lamexp_translation;
//Translator
-static QTranslator *g_lamexp_currentTranslator = NULL;
+static struct
+{
+ QVariant instance;
+ QReadWriteLock lock;
+}
+g_lamexp_currentTranslator;
//Shared memory
static const struct
static FILE *g_lamexp_log_file = NULL;
//CLI Arguments
-static QStringList *g_lamexp_argv = NULL;
+static struct
+{
+ QStringList list;
+ QReadWriteLock lock;
+}
+g_lamexp_argv;
///////////////////////////////////////////////////////////////////////////////
// GLOBAL FUNCTIONS
/*
* Detect CPU features
*/
-lamexp_cpu_t lamexp_detect_cpu_features(int argc, char **argv)
+lamexp_cpu_t lamexp_detect_cpu_features(const QStringList &argv)
{
typedef BOOL (WINAPI *IsWow64ProcessFun)(__in HANDLE hProcess, __out PBOOL Wow64Process);
typedef VOID (WINAPI *GetNativeSystemInfoFun)(__out LPSYSTEM_INFO lpSystemInfo);
features.x64 = true;
#endif
- if((argv != NULL) && (argc > 0))
+ if(argv.count() > 0)
{
bool flag = false;
- for(int i = 0; i < argc; i++)
+ for(int i = 0; i < argv.count(); i++)
{
- if(!_stricmp("--force-cpu-no-64bit", argv[i])) { flag = true; features.x64 = false; }
- if(!_stricmp("--force-cpu-no-sse", argv[i])) { flag = true; features.sse = features.sse2 = features.sse3 = features.ssse3 = false; }
- if(!_stricmp("--force-cpu-no-intel", argv[i])) { flag = true; features.intel = false; }
+ if(!argv[i].compare("--force-cpu-no-64bit", Qt::CaseInsensitive)) { flag = true; features.x64 = false; }
+ if(!argv[i].compare("--force-cpu-no-sse", Qt::CaseInsensitive)) { flag = true; features.sse = features.sse2 = features.sse3 = features.ssse3 = false; }
+ if(!argv[i].compare("--force-cpu-no-intel", Qt::CaseInsensitive)) { flag = true; features.intel = false; }
}
if(flag) qWarning("CPU flags overwritten by user-defined parameters. Take care!\n");
}
/*
* Check for compatibility mode
*/
-static bool lamexp_check_compatibility_mode(const char *exportName, const char *executableName)
+static bool lamexp_check_compatibility_mode(const char *exportName, const QString &executableName)
{
QLibrary kernel32("kernel32.dll");
if(kernel32.resolve(exportName) != NULL)
{
qWarning("Function '%s' exported from 'kernel32.dll' -> Windows compatibility mode!", exportName);
- qFatal("%s", QApplication::tr("Executable '%1' doesn't support Windows compatibility mode.").arg(QString::fromLatin1(executableName)).toLatin1().constData());
+ qFatal("%s", QApplication::tr("Executable '%1' doesn't support Windows compatibility mode.").arg(executableName).toLatin1().constData());
return false;
}
}
{
static bool qt_initialized = false;
typedef BOOL (WINAPI *SetDllDirectoryProc)(WCHAR *lpPathName);
+ const QStringList &arguments = lamexp_arguments();
//Don't initialized again, if done already
if(qt_initialized)
{
return true;
}
-
+
//Secure DLL loading
QLibrary kernel32("kernel32.dll");
if(kernel32.load())
}
//Extract executable name from argv[] array
- char *executableName = argv[0];
- while(char *temp = strpbrk(executableName, "\\/:?"))
+ QString executableName = QLatin1String("LameXP.exe");
+ if(arguments.count() > 0)
{
- executableName = temp + 1;
+ static const char *delimiters = "\\/:?";
+ executableName = arguments[0].trimmed();
+ for(int i = 0; delimiters[i]; i++)
+ {
+ int temp = executableName.lastIndexOf(QChar(delimiters[i]));
+ if(temp >= 0) executableName = executableName.mid(temp + 1);
+ }
+ executableName = executableName.trimmed();
+ if(executableName.isEmpty())
+ {
+ executableName = QLatin1String("LameXP.exe");
+ }
}
//Check Qt version
qDebug("Compiled with Qt v%s [%s], %s\n", QT_VERSION_STR, QT_PACKAGEDATE_STR, QT_BUILD_KEY);
if(_stricmp(qVersion(), QT_VERSION_STR))
{
- qFatal("%s", QApplication::tr("Executable '%1' requires Qt v%2, but found Qt v%3.").arg(QString::fromLatin1(executableName), QString::fromLatin1(QT_VERSION_STR), QString::fromLatin1(qVersion())).toLatin1().constData());
+ qFatal("%s", QApplication::tr("Executable '%1' requires Qt v%2, but found Qt v%3.").arg(executableName, QString::fromLatin1(QT_VERSION_STR), QString::fromLatin1(qVersion())).toLatin1().constData());
return false;
}
if(QLibraryInfo::buildKey().compare(QString::fromLatin1(QT_BUILD_KEY), Qt::CaseInsensitive))
{
- qFatal("%s", QApplication::tr("Executable '%1' was built for Qt '%2', but found Qt '%3'.").arg(QString::fromLatin1(executableName), QString::fromLatin1(QT_BUILD_KEY), QLibraryInfo::buildKey()).toLatin1().constData());
+ qFatal("%s", QApplication::tr("Executable '%1' was built for Qt '%2', but found Qt '%3'.").arg(executableName, QString::fromLatin1(QT_BUILD_KEY), QLibraryInfo::buildKey()).toLatin1().constData());
return false;
}
#else
{
case 0:
case QSysInfo::WV_NT:
- qFatal("%s", QApplication::tr("Executable '%1' requires Windows 2000 or later.").arg(QString::fromLatin1(executableName)).toLatin1().constData());
+ qFatal("%s", QApplication::tr("Executable '%1' requires Windows 2000 or later.").arg(executableName).toLatin1().constData());
break;
case QSysInfo::WV_2000:
qDebug("Running on Windows 2000 (not officially supported!).\n");
DWORD osVersionNo = lamexp_get_os_version();
if(LAMEXP_EQL_OS_VER(osVersionNo, 6, 2))
{
- qDebug("Running on Windows 8 (still experimental!)\n");
+ qDebug("Running on Windows 8 or Windows Server 2012\n");
lamexp_check_compatibility_mode(NULL, executableName);
}
else
}
//Add default translations
+ QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
g_lamexp_translation.files.insert(LAMEXP_DEFAULT_LANGID, "");
g_lamexp_translation.names.insert(LAMEXP_DEFAULT_LANGID, "English");
+ writeLockTranslations.unlock();
//Check for process elevation
if((!lamexp_check_elevation()) && (!lamexp_detect_wine()))
*/
const QString &lamexp_temp_folder2(void)
{
- static const char *TEMP_STR = "Temp";
- const QString WRITE_TEST_DATA = lamexp_rand_str();
- const QString SUB_FOLDER = lamexp_rand_str();
+ QReadLocker readLock(&g_lamexp_folder.lock);
//Already initialized?
- if(!g_lamexp_temp_folder.isEmpty())
+ if(!g_lamexp_folder.temp.isEmpty())
{
- if(QDir(g_lamexp_temp_folder).exists())
- {
- return g_lamexp_temp_folder;
- }
- else
+ if(QDir(g_lamexp_folder.temp).exists())
{
- g_lamexp_temp_folder.clear();
+ return g_lamexp_folder.temp;
}
}
+ readLock.unlock();
+ QWriteLocker writeLock(&g_lamexp_folder.lock);
+ g_lamexp_folder.temp.clear();
+
+ static const char *TEMP_STR = "Temp";
+ const QString WRITE_TEST_DATA = lamexp_rand_str();
+ const QString SUB_FOLDER = lamexp_rand_str();
+
//Try the %TMP% or %TEMP% directory first
QDir temp = QDir::temp();
if(temp.exists())
{
if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
{
- g_lamexp_temp_folder = temp.canonicalPath();
+ g_lamexp_folder.temp = temp.canonicalPath();
}
testFile.remove();
}
}
- if(!g_lamexp_temp_folder.isEmpty())
+ if(!g_lamexp_folder.temp.isEmpty())
{
- return g_lamexp_temp_folder;
+ return g_lamexp_folder.temp;
}
}
{
if(testFile.write(WRITE_TEST_DATA.toLatin1().constData()) >= strlen(WRITE_TEST_DATA.toLatin1().constData()))
{
- g_lamexp_temp_folder = localAppData.canonicalPath();
+ g_lamexp_folder.temp = localAppData.canonicalPath();
}
testFile.remove();
}
}
}
}
- if(!g_lamexp_temp_folder.isEmpty())
+ if(!g_lamexp_folder.temp.isEmpty())
{
- return g_lamexp_temp_folder;
+ return g_lamexp_folder.temp;
}
}
//Failed to create TEMP folder!
qFatal("Temporary directory could not be initialized!\n\nFirst attempt:\n%s\n\nSecond attempt:\n%s", temp.canonicalPath().toUtf8().constData(), localAppData.canonicalPath().toUtf8().constData());
- return g_lamexp_temp_folder;
+ return g_lamexp_folder.temp;
}
/*
*/
void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned int version)
{
- QWriteLocker writeLock(&g_lamexp_tool_lock);
+ QWriteLocker writeLock(&g_lamexp_tools.lock);
- if(g_lamexp_tool_registry.contains(toolName.toLower()))
+ if(g_lamexp_tools.registry.contains(toolName.toLower()))
{
throw "lamexp_register_tool: Tool is already registered!";
}
- g_lamexp_tool_registry.insert(toolName.toLower(), file);
- g_lamexp_tool_versions.insert(toolName.toLower(), version);
+ g_lamexp_tools.registry.insert(toolName.toLower(), file);
+ g_lamexp_tools.versions.insert(toolName.toLower(), version);
}
/*
*/
bool lamexp_check_tool(const QString &toolName)
{
- QReadLocker readLock(&g_lamexp_tool_lock);
- return g_lamexp_tool_registry.contains(toolName.toLower());
+ QReadLocker readLock(&g_lamexp_tools.lock);
+ return g_lamexp_tools.registry.contains(toolName.toLower());
}
/*
*/
const QString lamexp_lookup_tool(const QString &toolName)
{
- QReadLocker readLock(&g_lamexp_tool_lock);
+ QReadLocker readLock(&g_lamexp_tools.lock);
- if(g_lamexp_tool_registry.contains(toolName.toLower()))
+ if(g_lamexp_tools.registry.contains(toolName.toLower()))
{
- return g_lamexp_tool_registry.value(toolName.toLower())->filePath();
+ return g_lamexp_tools.registry.value(toolName.toLower())->filePath();
}
else
{
*/
unsigned int lamexp_tool_version(const QString &toolName)
{
- QReadLocker readLock(&g_lamexp_tool_lock);
+ QReadLocker readLock(&g_lamexp_tools.lock);
- if(g_lamexp_tool_versions.contains(toolName.toLower()))
+ if(g_lamexp_tools.versions.contains(toolName.toLower()))
{
- return g_lamexp_tool_versions.value(toolName.toLower());
+ return g_lamexp_tools.versions.value(toolName.toLower());
}
else
{
*/
bool lamexp_translation_register(const QString &langId, const QString &qmFile, const QString &langName, unsigned int &systemId, unsigned int &country)
{
+ QWriteLocker writeLockTranslations(&g_lamexp_translation.lock);
+
if(qmFile.isEmpty() || langName.isEmpty() || systemId < 1)
{
return false;
*/
QStringList lamexp_query_translations(void)
{
+ QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.files.keys();
}
*/
QString lamexp_translation_name(const QString &langId)
{
+ QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.names.value(langId.toLower(), QString());
}
*/
unsigned int lamexp_translation_sysid(const QString &langId)
{
+ QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.sysid.value(langId.toLower(), 0);
}
*/
unsigned int lamexp_translation_country(const QString &langId)
{
+ QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
return g_lamexp_translation.cntry.value(langId.toLower(), 0);
}
}
else
{
+ QReadLocker readLock(&g_lamexp_translation.lock);
QString qmFile = g_lamexp_translation.files.value(langId.toLower(), QString());
if(!qmFile.isEmpty())
{
*/
bool lamexp_install_translator_from_file(const QString &qmFile)
{
+ QWriteLocker writeLock(&g_lamexp_currentTranslator.lock);
bool success = false;
- if(!g_lamexp_currentTranslator)
+ if(!g_lamexp_currentTranslator.instance.isValid())
{
- g_lamexp_currentTranslator = new QTranslator();
+ g_lamexp_currentTranslator.instance.setValue<QObject*>(new QTranslator());
}
if(!qmFile.isEmpty())
{
QString qmPath = QFileInfo(qmFile).canonicalFilePath();
- QApplication::removeTranslator(g_lamexp_currentTranslator);
- success = g_lamexp_currentTranslator->load(qmPath);
- QApplication::installTranslator(g_lamexp_currentTranslator);
- if(!success)
+ QTranslator *poTranslator = dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>());
+ QApplication::removeTranslator(poTranslator);
+ if(success = poTranslator->load(qmPath))
+ {
+ QApplication::installTranslator(poTranslator);
+ }
+ else
{
qWarning("Failed to load translation:\n\"%s\"", qmPath.toLatin1().constData());
}
}
else
{
- QApplication::removeTranslator(g_lamexp_currentTranslator);
+ QApplication::removeTranslator(dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>()));
success = true;
}
const QStringList &lamexp_arguments(void)
{
- if(!g_lamexp_argv)
+ QReadLocker readLock(&g_lamexp_argv.lock);
+
+ if(g_lamexp_argv.list.isEmpty())
{
- g_lamexp_argv = new QStringList();
+ readLock.unlock();
+ QWriteLocker writeLock(&g_lamexp_argv.lock);
+
int nArgs = 0;
LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
{
for(int i = 0; i < nArgs; i++)
{
- *g_lamexp_argv << WCHAR2QSTR(szArglist[i]);
+ g_lamexp_argv.list << WCHAR2QSTR(szArglist[i]);
}
LocalFree(szArglist);
}
else
{
- qWarning("CommandLineToArgvW failed !!!");
+ qWarning("CommandLineToArgvW() has failed !!!");
}
}
- return *g_lamexp_argv;
+ return g_lamexp_argv.list;
}
/*
static const GUID GUID_PROGRAM_FILES = {0x905e63b6,0xc1bf,0x494e,{0xb2,0x9c,0x65,0xb7,0x32,0xd3,0xd2,0x1a}};
static const GUID GUID_SYSTEM_FOLDER = {0x1AC14E77,0x02E7,0x4E5D,{0xB7,0x44,0x2E,0xB1,0xAE,0x51,0x98,0xB7}};
- static SHGetKnownFolderPathFun SHGetKnownFolderPathPtr = NULL;
- static SHGetFolderPathFun SHGetFolderPathPtr = NULL;
-
- if((!SHGetKnownFolderPathPtr) && (!SHGetFolderPathPtr))
- {
- QLibrary kernel32Lib("shell32.dll");
- if(kernel32Lib.load())
- {
- SHGetKnownFolderPathPtr = (SHGetKnownFolderPathFun) kernel32Lib.resolve("SHGetKnownFolderPath");
- SHGetFolderPathPtr = (SHGetFolderPathFun) kernel32Lib.resolve("SHGetFolderPathW");
- }
- }
+ QReadLocker readLock(&g_lamexp_folder.lock);
int folderCSIDL = -1;
GUID folderGUID = {0x0000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}};
+ size_t folderCacheId = size_t(-1);
switch(folder_id)
{
case lamexp_folder_localappdata:
+ folderCacheId = 0;
folderCSIDL = CSIDL_LOCAL_APPDATA;
folderGUID = GUID_LOCAL_APPDATA;
break;
case lamexp_folder_programfiles:
+ folderCacheId = 1;
folderCSIDL = CSIDL_PROGRAM_FILES;
folderGUID = GUID_PROGRAM_FILES;
break;
case lamexp_folder_systemfolder:
+ folderCacheId = 2;
folderCSIDL = CSIDL_SYSTEM_FOLDER;
folderGUID = GUID_SYSTEM_FOLDER;
break;
default:
+ qWarning("Invalid 'known' folder was requested!");
return QString();
break;
}
+ //Already in cache?
+ if(!g_lamexp_folder.knownFolders[folderCacheId].isEmpty())
+ {
+ return g_lamexp_folder.knownFolders[folderCacheId];
+ }
+
+ readLock.unlock();
+ QWriteLocker writeLock(&g_lamexp_folder.lock);
+
+ static SHGetKnownFolderPathFun SHGetKnownFolderPathPtr = NULL;
+ static SHGetFolderPathFun SHGetFolderPathPtr = NULL;
+
+ if((!SHGetKnownFolderPathPtr) && (!SHGetFolderPathPtr))
+ {
+ QLibrary kernel32Lib("shell32.dll");
+ if(kernel32Lib.load())
+ {
+ SHGetKnownFolderPathPtr = (SHGetKnownFolderPathFun) kernel32Lib.resolve("SHGetKnownFolderPath");
+ SHGetFolderPathPtr = (SHGetFolderPathFun) kernel32Lib.resolve("SHGetFolderPathW");
+ }
+ }
+
QString folder;
if(SHGetKnownFolderPathPtr)
delete [] path;
}
+ //Update cache
+ if(!folder.isEmpty())
+ {
+ g_lamexp_folder.knownFolders[folderCacheId] = folder;
+ }
+
return folder;
}
}
/*
+ * Application entry point (runs before static initializers)
+ */
+extern "C"
+{
+ int WinMainCRTStartup(void);
+
+ int lamexp_entry_point(void)
+ {
+ if((!LAMEXP_DEBUG) && lamexp_check_for_debugger())
+ {
+ FatalAppExit(0, L"Not a debug build. Please unload debugger and try again!");
+ TerminateProcess(GetCurrentProcess(), -1);
+ }
+ return WinMainCRTStartup();
+ }
+}
+
+/*
* Finalization function (final clean-up)
*/
void lamexp_finalization(void)
qDebug("lamexp_finalization()");
//Free all tools
- if(!g_lamexp_tool_registry.isEmpty())
+ if(!g_lamexp_tools.registry.isEmpty())
{
- QStringList keys = g_lamexp_tool_registry.keys();
+ QStringList keys = g_lamexp_tools.registry.keys();
for(int i = 0; i < keys.count(); i++)
{
- LAMEXP_DELETE(g_lamexp_tool_registry[keys.at(i)]);
+ LAMEXP_DELETE(g_lamexp_tools.registry[keys.at(i)]);
}
- g_lamexp_tool_registry.clear();
- g_lamexp_tool_versions.clear();
+ g_lamexp_tools.registry.clear();
+ g_lamexp_tools.versions.clear();
}
//Delete temporary files
- if(!g_lamexp_temp_folder.isEmpty())
+ if(!g_lamexp_folder.temp.isEmpty())
{
for(int i = 0; i < 100; i++)
{
- if(lamexp_clean_folder(g_lamexp_temp_folder))
+ if(lamexp_clean_folder(g_lamexp_folder.temp))
{
break;
}
Sleep(125);
}
- g_lamexp_temp_folder.clear();
+ g_lamexp_folder.temp.clear();
}
//Clear languages
- if(g_lamexp_currentTranslator)
+ if(g_lamexp_currentTranslator.instance.isValid())
{
- QApplication::removeTranslator(g_lamexp_currentTranslator);
- LAMEXP_DELETE(g_lamexp_currentTranslator);
+ QTranslator *poTranslator = dynamic_cast<QTranslator*>(g_lamexp_currentTranslator.instance.value<QObject*>());
+ g_lamexp_currentTranslator.instance.clear();
+ QApplication::removeTranslator(poTranslator);
+ LAMEXP_DELETE(poTranslator);
}
g_lamexp_translation.files.clear();
g_lamexp_translation.names.clear();
+ g_lamexp_translation.cntry.clear();
+ g_lamexp_translation.sysid.clear();
//Destroy Qt application object
QApplication *application = dynamic_cast<QApplication*>(QApplication::instance());
}
//Free CLI Arguments
- LAMEXP_DELETE(g_lamexp_argv);
+ g_lamexp_argv.list.clear();
}
/*