OSDN Git Service

Made lamexp_arguments() thread-safe, just to be sure.
[lamexp/LameXP.git] / src / Global.cpp
index 78b628a..9ad35a5 100644 (file)
@@ -199,12 +199,22 @@ static const unsigned int g_lamexp_toolver_qaacenc = VER_LAMEXP_TOOL_QAAC;
 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
@@ -213,11 +223,17 @@ 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
@@ -262,7 +278,12 @@ static const DWORD g_main_thread_id = GetCurrentThreadId();
 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
@@ -625,7 +646,7 @@ void lamexp_init_console(const QStringList &argv)
 /*
  * 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);
@@ -720,14 +741,14 @@ lamexp_cpu_t lamexp_detect_cpu_features(int argc, char **argv)
        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");
        }
@@ -804,7 +825,7 @@ static HANDLE lamexp_debug_thread_init(void)
 /*
  * 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");
 
@@ -813,7 +834,7 @@ static bool lamexp_check_compatibility_mode(const char *exportName, const char *
                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;
                }
        }
@@ -1027,13 +1048,14 @@ bool lamexp_init_qt(int argc, char* argv[])
 {
        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())
@@ -1044,10 +1066,21 @@ bool lamexp_init_qt(int argc, char* argv[])
        }
 
        //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
@@ -1056,12 +1089,12 @@ bool lamexp_init_qt(int argc, char* argv[])
        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
@@ -1074,7 +1107,7 @@ bool lamexp_init_qt(int argc, char* argv[])
        {
        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");
@@ -1101,7 +1134,7 @@ bool lamexp_init_qt(int argc, char* argv[])
                        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
@@ -1148,8 +1181,10 @@ bool lamexp_init_qt(int argc, char* argv[])
        }
        
        //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()))
@@ -1378,23 +1413,25 @@ QString lamexp_rand_str(void)
  */
 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())
@@ -1407,14 +1444,14 @@ const QString &lamexp_temp_folder2(void)
                        {
                                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;
                }
        }
 
@@ -1442,22 +1479,22 @@ const QString &lamexp_temp_folder2(void)
                                        {
                                                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;
 }
 
 /*
@@ -1495,15 +1532,15 @@ bool lamexp_clean_folder(const QString &folderPath)
  */
 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);
 }
 
 /*
@@ -1511,8 +1548,8 @@ void lamexp_register_tool(const QString &toolName, LockedFile *file, unsigned in
  */
 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());
 }
 
 /*
@@ -1520,11 +1557,11 @@ bool lamexp_check_tool(const QString &toolName)
  */
 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
        {
@@ -1537,11 +1574,11 @@ const QString lamexp_lookup_tool(const QString &toolName)
  */
 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
        {
@@ -1585,6 +1622,8 @@ const QString lamexp_version2string(const QString &pattern, unsigned int version
  */
 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;
@@ -1603,6 +1642,7 @@ bool lamexp_translation_register(const QString &langId, const QString &qmFile, c
  */
 QStringList lamexp_query_translations(void)
 {
+       QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
        return g_lamexp_translation.files.keys();
 }
 
@@ -1611,6 +1651,7 @@ QStringList lamexp_query_translations(void)
  */
 QString lamexp_translation_name(const QString &langId)
 {
+       QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
        return g_lamexp_translation.names.value(langId.toLower(), QString());
 }
 
@@ -1619,6 +1660,7 @@ QString lamexp_translation_name(const QString &langId)
  */
 unsigned int lamexp_translation_sysid(const QString &langId)
 {
+       QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
        return g_lamexp_translation.sysid.value(langId.toLower(), 0);
 }
 
@@ -1627,6 +1669,7 @@ unsigned int lamexp_translation_sysid(const QString &langId)
  */
 unsigned int lamexp_translation_country(const QString &langId)
 {
+       QReadLocker writeLockTranslations(&g_lamexp_translation.lock);
        return g_lamexp_translation.cntry.value(langId.toLower(), 0);
 }
 
@@ -1643,6 +1686,7 @@ bool lamexp_install_translator(const QString &langId)
        }
        else
        {
+               QReadLocker readLock(&g_lamexp_translation.lock);
                QString qmFile = g_lamexp_translation.files.value(langId.toLower(), QString());
                if(!qmFile.isEmpty())
                {
@@ -1662,27 +1706,31 @@ bool lamexp_install_translator(const QString &langId)
  */
 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;
        }
 
@@ -1691,9 +1739,13 @@ bool lamexp_install_translator_from_file(const QString &qmFile)
 
 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);
 
@@ -1701,17 +1753,17 @@ const QStringList &lamexp_arguments(void)
                {
                        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;
 }
 
 /*
@@ -1730,41 +1782,57 @@ QString lamexp_known_folder(lamexp_known_folder_t folder_id)
        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)
@@ -1804,6 +1872,12 @@ QString lamexp_known_folder(lamexp_known_folder_t folder_id)
                delete [] path;
        }
 
+       //Update cache
+       if(!folder.isEmpty())
+       {
+               g_lamexp_folder.knownFolders[folderCacheId] = folder;
+       }
+
        return folder;
 }
 
@@ -2057,6 +2131,24 @@ QStringList lamexp_available_codepages(bool noAliases)
 }
 
 /*
+ * 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)
@@ -2064,39 +2156,43 @@ 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());
@@ -2133,7 +2229,7 @@ void lamexp_finalization(void)
        }
 
        //Free CLI Arguments
-       LAMEXP_DELETE(g_lamexp_argv);
+       g_lamexp_argv.list.clear();
 }
 
 /*