1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
26 #include "Targetver.h"
28 //Visual Leaks Detector
33 #define WIN32_LEAN_AND_MEAN
44 #include <QApplication>
49 #include <QImageReader>
51 #include <QLibraryInfo>
53 #include <QMessageBox>
54 #include <QPlastiqueStyle>
56 #include <QReadWriteLock>
61 #include <QTranslator>
66 #define LAMEXP_INC_CONFIG
82 //Initialize static Qt plugins
84 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
88 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin
)
89 Q_IMPORT_PLUGIN(QICOPlugin
)
93 ///////////////////////////////////////////////////////////////////////////////
95 ///////////////////////////////////////////////////////////////////////////////
97 #define _LAMEXP_MAKE_STR(STR) #STR
98 #define LAMEXP_MAKE_STR(STR) _LAMEXP_MAKE_STR(STR)
101 #define CLEAN_OUTPUT_STRING(STR) do \
103 const char CTRL_CHARS[3] = { '\r', '\n', '\t' }; \
104 for(size_t i = 0; i < 3; i++) \
106 while(char *pos = strchr((STR), CTRL_CHARS[i])) *pos = char(0x20); \
112 #define TRIM_LEFT(STR) do \
114 const char WHITE_SPACE[4] = { char(0x20), '\r', '\n', '\t' }; \
115 for(size_t i = 0; i < 4; i++) \
117 while(*(STR) == WHITE_SPACE[i]) (STR)++; \
122 ///////////////////////////////////////////////////////////////////////////////
124 ///////////////////////////////////////////////////////////////////////////////
126 typedef HRESULT (WINAPI
*SHGetKnownFolderPath_t
)(const GUID
&rfid
, DWORD dwFlags
, HANDLE hToken
, PWSTR
*ppszPath
);
127 typedef HRESULT (WINAPI
*SHGetFolderPath_t
)(HWND hwndOwner
, int nFolder
, HANDLE hToken
, DWORD dwFlags
, LPWSTR pszPath
);
129 ///////////////////////////////////////////////////////////////////////////////
131 ///////////////////////////////////////////////////////////////////////////////
134 * wrapper for native Win32 critical sections
136 class CriticalSection
139 inline CriticalSection(void)
141 InitializeCriticalSection(&m_win32criticalSection
);
144 inline ~CriticalSection(void)
146 DeleteCriticalSection(&m_win32criticalSection
);
149 inline void enter(void)
151 EnterCriticalSection(&m_win32criticalSection
);
154 inline bool tryEnter(void)
156 return TryEnterCriticalSection(&m_win32criticalSection
);
159 inline void leave(void)
161 LeaveCriticalSection(&m_win32criticalSection
);
165 CRITICAL_SECTION m_win32criticalSection
;
169 * RAII-style critical section locker
174 inline CSLocker(CriticalSection
&criticalSection
)
177 m_criticalSection(criticalSection
)
179 m_criticalSection
.enter();
183 inline ~CSLocker(void)
188 inline void forceUnlock(void)
192 m_criticalSection
.leave();
197 volatile bool m_locked
;
198 CriticalSection
&m_criticalSection
;
201 ///////////////////////////////////////////////////////////////////////////////
203 ///////////////////////////////////////////////////////////////////////////////
205 //Console attached flag
206 static bool g_lamexp_console_attached
= false;
209 static volatile bool g_lamexp_fatal_flag
= true;
210 static CriticalSection g_lamexp_fatal_lock
;
213 static CriticalSection g_lamexp_message_lock
;
218 QMap
<size_t, QString
> *knownFolders
;
219 SHGetKnownFolderPath_t getKnownFolderPath
;
220 SHGetFolderPath_t getFolderPath
;
223 g_lamexp_known_folder
;
237 lamexp_os_version_t version
;
251 //Win32 Theme support
258 g_lamexp_themes_enabled
;
260 //Win32 DWM API functions
264 HRESULT (__stdcall
*dwmIsCompositionEnabled
)(BOOL
*bEnabled
);
265 HRESULT (__stdcall
*dwmExtendFrameIntoClientArea
)(HWND hWnd
, const MARGINS
* pMarInset
);
266 HRESULT (__stdcall
*dwmEnableBlurBehindWindow
)(HWND hWnd
, const DWM_BLURBEHIND
* pBlurBehind
);
267 QLibrary
*dwmapi_dll
;
275 QHash
<const QString
, const unsigned char*> *sound_db
;
281 static const char *g_lamexp_imageformats
[] = {"bmp", "png", "jpg", "gif", "ico", "xpm", NULL
}; //"svg"
284 static const DWORD g_main_thread_id
= GetCurrentThreadId();
287 static FILE *g_lamexp_log_file
= NULL
;
290 const char* LAMEXP_DEFAULT_LANGID
= "en";
291 const char* LAMEXP_DEFAULT_TRANSLATION
= "LameXP_EN.qm";
293 //Known Windows versions - maps marketing names to the actual Windows NT versions
294 const lamexp_os_version_t lamexp_winver_win2k
= {5,0};
295 const lamexp_os_version_t lamexp_winver_winxp
= {5,1};
296 const lamexp_os_version_t lamexp_winver_xpx64
= {5,2};
297 const lamexp_os_version_t lamexp_winver_vista
= {6,0};
298 const lamexp_os_version_t lamexp_winver_win70
= {6,1};
299 const lamexp_os_version_t lamexp_winver_win80
= {6,2};
300 const lamexp_os_version_t lamexp_winver_win81
= {6,3};
303 static const char *GURU_MEDITATION
= "\n\nGURU MEDITATION !!!\n\n";
305 ///////////////////////////////////////////////////////////////////////////////
307 ///////////////////////////////////////////////////////////////////////////////
310 * Verify a specific Windows version
312 static bool lamexp_verify_os_version(const DWORD major
, const DWORD minor
)
314 OSVERSIONINFOEXW osvi
;
315 DWORDLONG dwlConditionMask
= 0;
317 //Initialize the OSVERSIONINFOEX structure
318 memset(&osvi
, 0, sizeof(OSVERSIONINFOEXW
));
319 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXW
);
320 osvi
.dwMajorVersion
= major
;
321 osvi
.dwMinorVersion
= minor
;
322 osvi
.dwPlatformId
= VER_PLATFORM_WIN32_NT
;
324 //Initialize the condition mask
325 VER_SET_CONDITION(dwlConditionMask
, VER_MAJORVERSION
, VER_GREATER_EQUAL
);
326 VER_SET_CONDITION(dwlConditionMask
, VER_MINORVERSION
, VER_GREATER_EQUAL
);
327 VER_SET_CONDITION(dwlConditionMask
, VER_PLATFORMID
, VER_EQUAL
);
330 const BOOL ret
= VerifyVersionInfoW(&osvi
, VER_MAJORVERSION
| VER_MINORVERSION
| VER_PLATFORMID
, dwlConditionMask
);
335 if(GetLastError() != ERROR_OLD_WIN_VERSION
)
337 qWarning("VerifyVersionInfo() system call has failed!");
341 return (ret
!= FALSE
);
345 * Determine the *real* Windows version
347 static bool lamexp_get_real_os_version(unsigned int *major
, unsigned int *minor
, bool *pbOverride
)
352 //Initialize local variables
353 OSVERSIONINFOEXW osvi
;
354 memset(&osvi
, 0, sizeof(OSVERSIONINFOEXW
));
355 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXW
);
357 //Try GetVersionEx() first
358 if(GetVersionExW((LPOSVERSIONINFOW
)&osvi
) == FALSE
)
360 qWarning("GetVersionEx() has failed, cannot detect Windows version!");
364 //Make sure we are running on NT
365 if(osvi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
367 *major
= osvi
.dwMajorVersion
;
368 *minor
= osvi
.dwMinorVersion
;
372 qWarning("Not running on Windows NT, unsupported operating system!");
376 //Determine the real *major* version first
379 const DWORD nextMajor
= (*major
) + 1;
380 if(lamexp_verify_os_version(nextMajor
, 0))
390 //Now also determine the real *minor* version
393 const DWORD nextMinor
= (*minor
) + 1;
394 if(lamexp_verify_os_version((*major
), nextMinor
))
407 * Get the native operating system version
409 const lamexp_os_version_t
&lamexp_get_os_version(void)
411 QReadLocker
readLock(&g_lamexp_os_version
.lock
);
413 //Already initialized?
414 if(g_lamexp_os_version
.bInitialized
)
416 return g_lamexp_os_version
.version
;
420 QWriteLocker
writeLock(&g_lamexp_os_version
.lock
);
423 if(!g_lamexp_os_version
.bInitialized
)
425 unsigned int major
, minor
; bool oflag
;
426 if(lamexp_get_real_os_version(&major
, &minor
, &oflag
))
428 g_lamexp_os_version
.version
.versionMajor
= major
;
429 g_lamexp_os_version
.version
.versionMinor
= minor
;
430 g_lamexp_os_version
.version
.overrideFlag
= oflag
;
431 g_lamexp_os_version
.bInitialized
= true;
435 qWarning("Failed to determin the operating system version!");
439 return g_lamexp_os_version
.version
;
443 * Check if we are running under wine
445 bool lamexp_detect_wine(void)
447 QReadLocker
readLock(&g_lamexp_wine
.lock
);
449 //Already initialized?
450 if(g_lamexp_wine
.bInitialized
)
452 return g_lamexp_wine
.bIsWine
;
456 QWriteLocker
writeLock(&g_lamexp_wine
.lock
);
458 if(!g_lamexp_wine
.bInitialized
)
460 g_lamexp_wine
.bIsWine
= false;
461 QLibrary
ntdll("ntdll.dll");
464 if(ntdll
.resolve("wine_nt_to_unix_file_name") != NULL
) g_lamexp_wine
.bIsWine
= true;
465 if(ntdll
.resolve("wine_get_version") != NULL
) g_lamexp_wine
.bIsWine
= true;
468 g_lamexp_wine
.bInitialized
= true;
471 return g_lamexp_wine
.bIsWine
;
475 * Change console text color
477 static void lamexp_console_color(FILE* file
, WORD attributes
)
479 const HANDLE hConsole
= (HANDLE
)(_get_osfhandle(_fileno(file
)));
480 if((hConsole
!= NULL
) && (hConsole
!= INVALID_HANDLE_VALUE
))
482 SetConsoleTextAttribute(hConsole
, attributes
);
487 * Output logging message to console
489 static void lamexp_write_console(const int type
, const char *msg
)
493 if(_isatty(_fileno(stderr
)))
495 UINT oldOutputCP
= GetConsoleOutputCP();
496 if(oldOutputCP
!= CP_UTF8
) SetConsoleOutputCP(CP_UTF8
);
502 lamexp_console_color(stderr
, FOREGROUND_RED
| FOREGROUND_INTENSITY
);
503 fprintf(stderr
, GURU_MEDITATION
);
504 fprintf(stderr
, "%s\n", msg
);
508 lamexp_console_color(stderr
, FOREGROUND_GREEN
| FOREGROUND_RED
| FOREGROUND_INTENSITY
);
509 fprintf(stderr
, "%s\n", msg
);
513 lamexp_console_color(stderr
, FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
| FOREGROUND_INTENSITY
);
514 fprintf(stderr
, "%s\n", msg
);
519 lamexp_console_color(stderr
, FOREGROUND_BLUE
| FOREGROUND_GREEN
| FOREGROUND_RED
);
520 if(oldOutputCP
!= CP_UTF8
) SetConsoleOutputCP(oldOutputCP
);
525 /*ignore any exception that might occur here!*/
530 * Output logging message to debugger
532 static void lamexp_write_dbg_out(const int type
, const char *msg
)
534 const char *FORMAT
= "[LameXP][%c] %s\n";
539 const char* input
= msg
;
546 _snprintf_s(buffer
, 512, _TRUNCATE
, FORMAT
, 'C', input
);
549 _snprintf_s(buffer
, 512, _TRUNCATE
, FORMAT
, 'W', input
);
552 _snprintf_s(buffer
, 512, _TRUNCATE
, FORMAT
, 'I', input
);
556 char *temp
= &buffer
[0];
557 CLEAN_OUTPUT_STRING(temp
);
558 OutputDebugStringA(temp
);
562 /*ignore any exception that might occur here!*/
567 * Output logging message to logfile
569 static void lamexp_write_logfile(const int type
, const char *msg
)
571 const char *FORMAT
= "[%c][%04u] %s\r\n";
575 if(g_lamexp_log_file
)
578 strncpy_s(buffer
, 512, msg
, _TRUNCATE
);
580 char *temp
= &buffer
[0];
582 CLEAN_OUTPUT_STRING(temp
);
584 const unsigned int timestamp
= static_cast<unsigned int>(_time64(NULL
) % 3600I64
);
590 fprintf(g_lamexp_log_file
, FORMAT
, 'C', timestamp
, temp
);
593 fprintf(g_lamexp_log_file
, FORMAT
, 'W', timestamp
, temp
);
596 fprintf(g_lamexp_log_file
, FORMAT
, 'I', timestamp
, temp
);
600 fflush(g_lamexp_log_file
);
605 /*ignore any exception that might occur here!*/
612 void lamexp_message_handler(QtMsgType type
, const char *msg
)
614 if((!msg
) || (!(msg
[0])))
619 CSLocker
lock(g_lamexp_message_lock
);
621 if(g_lamexp_log_file
)
623 lamexp_write_logfile(type
, msg
);
626 if(g_lamexp_console_attached
)
628 lamexp_write_console(type
, msg
);
632 lamexp_write_dbg_out(type
, msg
);
635 if((type
== QtCriticalMsg
) || (type
== QtFatalMsg
))
638 lamexp_fatal_exit(msg
);
643 * Invalid parameters handler
645 static void lamexp_invalid_param_handler(const wchar_t* exp
, const wchar_t* fun
, const wchar_t* fil
, unsigned int, uintptr_t)
647 lamexp_fatal_exit("Invalid parameter handler invoked, application will exit!");
653 static void lamexp_signal_handler(int signal_num
)
655 signal(signal_num
, lamexp_signal_handler
);
656 lamexp_fatal_exit("Signal handler invoked, application will exit!");
660 * Global exception handler
662 static LONG WINAPI
lamexp_exception_handler(struct _EXCEPTION_POINTERS
*ExceptionInfo
)
664 lamexp_fatal_exit("Unhandeled exception handler invoked, application will exit!");
669 * Initialize error handlers
671 void lamexp_init_error_handlers(void)
673 SetErrorMode(SEM_FAILCRITICALERRORS
| SEM_NOOPENFILEERRORBOX
);
674 SetUnhandledExceptionFilter(lamexp_exception_handler
);
675 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
676 _set_invalid_parameter_handler(lamexp_invalid_param_handler
);
678 static const int signal_num
[6] = { SIGABRT
, SIGFPE
, SIGILL
, SIGINT
, SIGSEGV
, SIGTERM
};
680 for(size_t i
= 0; i
< 6; i
++)
682 signal(signal_num
[i
], lamexp_signal_handler
);
687 * Initialize the console
689 void lamexp_init_console(const QStringList
&argv
)
691 bool enableConsole
= (LAMEXP_DEBUG
) || ((VER_LAMEXP_CONSOLE_ENABLED
) && lamexp_version_demo());
695 wchar_t *logfile
= NULL
;
696 size_t logfile_len
= 0;
697 if(!_wdupenv_s(&logfile
, &logfile_len
, L
"LAMEXP_LOGFILE"))
699 if(logfile
&& (logfile_len
> 0))
702 if(!_wfopen_s(&temp
, logfile
, L
"wb"))
704 fprintf(temp
, "%c%c%c", char(0xEF), char(0xBB), char(0xBF));
705 g_lamexp_log_file
= temp
;
714 for(int i
= 0; i
< argv
.count(); i
++)
716 if(!argv
.at(i
).compare("--console", Qt::CaseInsensitive
))
718 enableConsole
= true;
720 else if(!argv
.at(i
).compare("--no-console", Qt::CaseInsensitive
))
722 enableConsole
= false;
729 if(!g_lamexp_console_attached
)
731 if(AllocConsole() != FALSE
)
733 SetConsoleCtrlHandler(NULL
, TRUE
);
734 SetConsoleTitle(L
"LameXP - Audio Encoder Front-End | Debug Console");
735 SetConsoleOutputCP(CP_UTF8
);
736 g_lamexp_console_attached
= true;
740 if(g_lamexp_console_attached
)
742 //-------------------------------------------------------------------
743 //See: http://support.microsoft.com/default.aspx?scid=kb;en-us;105305
744 //-------------------------------------------------------------------
745 const int flags
= _O_WRONLY
| _O_U8TEXT
;
746 int hCrtStdOut
= _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE
), flags
);
747 int hCrtStdErr
= _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE
), flags
);
748 FILE *hfStdOut
= (hCrtStdOut
>= 0) ? _fdopen(hCrtStdOut
, "wb") : NULL
;
749 FILE *hfStdErr
= (hCrtStdErr
>= 0) ? _fdopen(hCrtStdErr
, "wb") : NULL
;
750 if(hfStdOut
) { *stdout
= *hfStdOut
; std::cout
.rdbuf(new std::filebuf(hfStdOut
)); }
751 if(hfStdErr
) { *stderr
= *hfStdErr
; std::cerr
.rdbuf(new std::filebuf(hfStdErr
)); }
754 HWND hwndConsole
= GetConsoleWindow();
756 if((hwndConsole
!= NULL
) && (hwndConsole
!= INVALID_HANDLE_VALUE
))
758 HMENU hMenu
= GetSystemMenu(hwndConsole
, 0);
759 EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
| MF_GRAYED
);
760 RemoveMenu(hMenu
, SC_CLOSE
, MF_BYCOMMAND
);
762 SetWindowPos(hwndConsole
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_FRAMECHANGED
);
763 SetWindowLong(hwndConsole
, GWL_STYLE
, GetWindowLong(hwndConsole
, GWL_STYLE
) & (~WS_MAXIMIZEBOX
) & (~WS_MINIMIZEBOX
));
764 SetWindowPos(hwndConsole
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
|SWP_NOZORDER
|SWP_FRAMECHANGED
);
770 * Detect CPU features
772 lamexp_cpu_t
lamexp_detect_cpu_features(const QStringList
&argv
)
774 typedef BOOL (WINAPI
*IsWow64ProcessFun
)(__in HANDLE hProcess
, __out PBOOL Wow64Process
);
776 lamexp_cpu_t features
;
777 SYSTEM_INFO systemInfo
;
778 int CPUInfo
[4] = {-1};
779 char CPUIdentificationString
[0x40];
780 char CPUBrandString
[0x40];
782 memset(&features
, 0, sizeof(lamexp_cpu_t
));
783 memset(&systemInfo
, 0, sizeof(SYSTEM_INFO
));
784 memset(CPUIdentificationString
, 0, sizeof(CPUIdentificationString
));
785 memset(CPUBrandString
, 0, sizeof(CPUBrandString
));
788 memcpy(CPUIdentificationString
, &CPUInfo
[1], sizeof(int));
789 memcpy(CPUIdentificationString
+ 4, &CPUInfo
[3], sizeof(int));
790 memcpy(CPUIdentificationString
+ 8, &CPUInfo
[2], sizeof(int));
791 features
.intel
= (_stricmp(CPUIdentificationString
, "GenuineIntel") == 0);
792 strncpy_s(features
.vendor
, 0x40, CPUIdentificationString
, _TRUNCATE
);
797 features
.mmx
= (CPUInfo
[3] & 0x800000) || false;
798 features
.sse
= (CPUInfo
[3] & 0x2000000) || false;
799 features
.sse2
= (CPUInfo
[3] & 0x4000000) || false;
800 features
.ssse3
= (CPUInfo
[2] & 0x200) || false;
801 features
.sse3
= (CPUInfo
[2] & 0x1) || false;
802 features
.ssse3
= (CPUInfo
[2] & 0x200) || false;
803 features
.stepping
= CPUInfo
[0] & 0xf;
804 features
.model
= ((CPUInfo
[0] >> 4) & 0xf) + (((CPUInfo
[0] >> 16) & 0xf) << 4);
805 features
.family
= ((CPUInfo
[0] >> 8) & 0xf) + ((CPUInfo
[0] >> 20) & 0xff);
808 __cpuid(CPUInfo
, 0x80000000);
809 int nExIds
= qMax
<int>(qMin
<int>(CPUInfo
[0], 0x80000004), 0x80000000);
811 for(int i
= 0x80000002; i
<= nExIds
; ++i
)
817 memcpy(CPUBrandString
, CPUInfo
, sizeof(CPUInfo
));
820 memcpy(CPUBrandString
+ 16, CPUInfo
, sizeof(CPUInfo
));
823 memcpy(CPUBrandString
+ 32, CPUInfo
, sizeof(CPUInfo
));
828 strncpy_s(features
.brand
, 0x40, CPUBrandString
, _TRUNCATE
);
830 if(strlen(features
.brand
) < 1) strncpy_s(features
.brand
, 0x40, "Unknown", _TRUNCATE
);
831 if(strlen(features
.vendor
) < 1) strncpy_s(features
.vendor
, 0x40, "Unknown", _TRUNCATE
);
833 #if (!(defined(_M_X64) || defined(_M_IA64)))
834 QLibrary
Kernel32Lib("kernel32.dll");
835 if(IsWow64ProcessFun IsWow64ProcessPtr
= (IsWow64ProcessFun
) Kernel32Lib
.resolve("IsWow64Process"))
837 BOOL x64flag
= FALSE
;
838 if(IsWow64ProcessPtr(GetCurrentProcess(), &x64flag
))
840 features
.x64
= (x64flag
== TRUE
);
847 DWORD_PTR procAffinity
, sysAffinity
;
848 if(GetProcessAffinityMask(GetCurrentProcess(), &procAffinity
, &sysAffinity
))
850 for(DWORD_PTR mask
= 1; mask
; mask
<<= 1)
852 features
.count
+= ((sysAffinity
& mask
) ? (1) : (0));
855 if(features
.count
< 1)
857 GetNativeSystemInfo(&systemInfo
);
858 features
.count
= qBound(1UL, systemInfo
.dwNumberOfProcessors
, 64UL);
864 for(int i
= 0; i
< argv
.count(); i
++)
866 if(!argv
[i
].compare("--force-cpu-no-64bit", Qt::CaseInsensitive
)) { flag
= true; features
.x64
= false; }
867 if(!argv
[i
].compare("--force-cpu-no-sse", Qt::CaseInsensitive
)) { flag
= true; features
.sse
= features
.sse2
= features
.sse3
= features
.ssse3
= false; }
868 if(!argv
[i
].compare("--force-cpu-no-intel", Qt::CaseInsensitive
)) { flag
= true; features
.intel
= false; }
870 if(flag
) qWarning("CPU flags overwritten by user-defined parameters. Take care!\n");
877 * Check for debugger (detect routine)
879 static __forceinline
bool lamexp_check_for_debugger(void)
883 CloseHandle((HANDLE
)((DWORD_PTR
)-3));
890 BOOL bHaveDebugger
= FALSE
;
891 if(CheckRemoteDebuggerPresent(GetCurrentProcess(), &bHaveDebugger
))
893 if(bHaveDebugger
) return true;
896 return IsDebuggerPresent();
900 * Check for debugger (thread proc)
902 static unsigned int __stdcall
lamexp_debug_thread_proc(LPVOID lpParameter
)
904 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST
);
907 if(lamexp_check_for_debugger())
909 lamexp_fatal_exit("Not a debug build. Please unload debugger and try again!");
917 * Check for debugger (startup routine)
919 static HANDLE
lamexp_debug_thread_init()
921 if(lamexp_check_for_debugger())
923 lamexp_fatal_exit("Not a debug build. Please unload debugger and try again!");
925 const uintptr_t h
= _beginthreadex(NULL
, 0, lamexp_debug_thread_proc
, NULL
, 0, NULL
);
926 return (HANDLE
)(h
^0xdeadbeef);
932 static bool lamexp_event_filter(void *message
, long *result
)
934 if((!(LAMEXP_DEBUG
)) && lamexp_check_for_debugger())
936 lamexp_fatal_exit("Not a debug build. Please unload debugger and try again!");
939 switch(reinterpret_cast<MSG
*>(message
)->message
)
941 case WM_QUERYENDSESSION
:
942 qWarning("WM_QUERYENDSESSION message received!");
943 *result
= lamexp_broadcast(lamexp_event_queryendsession
, false) ? TRUE
: FALSE
;
946 qWarning("WM_ENDSESSION message received!");
947 if(reinterpret_cast<MSG
*>(message
)->wParam
== TRUE
)
949 lamexp_broadcast(lamexp_event_endsession
, false);
950 if(QApplication
*app
= reinterpret_cast<QApplication
*>(QApplication::instance()))
952 app
->closeAllWindows();
955 lamexp_finalization();
961 /*ignore this message and let Qt handle it*/
967 * Check for process elevation
969 static bool lamexp_process_is_elevated(bool *bIsUacEnabled
= NULL
)
971 bool bIsProcessElevated
= false;
972 if(bIsUacEnabled
) *bIsUacEnabled
= false;
973 HANDLE hToken
= NULL
;
975 if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
977 TOKEN_ELEVATION_TYPE tokenElevationType
;
979 if(GetTokenInformation(hToken
, TokenElevationType
, &tokenElevationType
, sizeof(TOKEN_ELEVATION_TYPE
), &returnLength
))
981 if(returnLength
== sizeof(TOKEN_ELEVATION_TYPE
))
983 switch(tokenElevationType
)
985 case TokenElevationTypeDefault
:
986 qDebug("Process token elevation type: Default -> UAC is disabled.\n");
988 case TokenElevationTypeFull
:
989 qWarning("Process token elevation type: Full -> potential security risk!\n");
990 bIsProcessElevated
= true;
991 if(bIsUacEnabled
) *bIsUacEnabled
= true;
993 case TokenElevationTypeLimited
:
994 qDebug("Process token elevation type: Limited -> not elevated.\n");
995 if(bIsUacEnabled
) *bIsUacEnabled
= true;
998 qWarning("Unknown tokenElevationType value: %d", tokenElevationType
);
1004 qWarning("GetTokenInformation() return an unexpected size!");
1007 CloseHandle(hToken
);
1011 qWarning("Failed to open process token!");
1014 return bIsProcessElevated
;
1018 * Convert QIcon to HICON -> caller is responsible for destroying the HICON!
1020 static HICON
lamexp_qicon2hicon(const QIcon
&icon
, const int w
, const int h
)
1024 QPixmap pixmap
= icon
.pixmap(w
, h
);
1025 if(!pixmap
.isNull())
1027 return pixmap
.toWinHICON();
1034 * Initialize Qt framework
1036 bool lamexp_init_qt(int argc
, char* argv
[])
1038 static bool qt_initialized
= false;
1039 typedef BOOL (WINAPI
*SetDllDirectoryProc
)(WCHAR
*lpPathName
);
1040 const QStringList
&arguments
= lamexp_arguments();
1042 //Don't initialized again, if done already
1048 //Secure DLL loading
1049 QLibrary
kernel32("kernel32.dll");
1052 SetDllDirectoryProc pSetDllDirectory
= (SetDllDirectoryProc
) kernel32
.resolve("SetDllDirectoryW");
1053 if(pSetDllDirectory
!= NULL
) pSetDllDirectory(L
"");
1056 //Extract executable name from argv[] array
1057 QString executableName
= QLatin1String("LameXP.exe");
1058 if(arguments
.count() > 0)
1060 static const char *delimiters
= "\\/:?";
1061 executableName
= arguments
[0].trimmed();
1062 for(int i
= 0; delimiters
[i
]; i
++)
1064 int temp
= executableName
.lastIndexOf(QChar(delimiters
[i
]));
1065 if(temp
>= 0) executableName
= executableName
.mid(temp
+ 1);
1067 executableName
= executableName
.trimmed();
1068 if(executableName
.isEmpty())
1070 executableName
= QLatin1String("LameXP.exe");
1076 qDebug("Using Qt v%s [%s], %s, %s", qVersion(), QLibraryInfo::buildDate().toString(Qt::ISODate
).toLatin1().constData(), (qSharedBuild() ? "DLL" : "Static"), QLibraryInfo::buildKey().toLatin1().constData());
1077 qDebug("Compiled with Qt v%s [%s], %s\n", QT_VERSION_STR
, QT_PACKAGEDATE_STR
, QT_BUILD_KEY
);
1078 if(_stricmp(qVersion(), QT_VERSION_STR
))
1080 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());
1083 if(QLibraryInfo::buildKey().compare(QString::fromLatin1(QT_BUILD_KEY
), Qt::CaseInsensitive
))
1085 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());
1089 qDebug("Using Qt v%s [%s], %s", qVersion(), QLibraryInfo::buildDate().toString(Qt::ISODate
).toLatin1().constData(), (qSharedBuild() ? "DLL" : "Static"));
1090 qDebug("Compiled with Qt v%s [%s]\n", QT_VERSION_STR
, QT_PACKAGEDATE_STR
);
1093 //Check the Windows version
1094 const lamexp_os_version_t
&osVersionNo
= lamexp_get_os_version();
1095 if(osVersionNo
< lamexp_winver_winxp
)
1097 qFatal("%s", QApplication::tr("Executable '%1' requires Windows XP or later.").arg(executableName
).toLatin1().constData());
1100 //Supported Windows version?
1101 if(osVersionNo
== lamexp_winver_winxp
)
1103 qDebug("Running on Windows XP or Windows XP Media Center Edition.\n"); //lamexp_check_compatibility_mode("GetLargePageMinimum", executableName);
1105 else if(osVersionNo
== lamexp_winver_xpx64
)
1107 qDebug("Running on Windows Server 2003, Windows Server 2003 R2 or Windows XP x64.\n"); //lamexp_check_compatibility_mode("GetLocaleInfoEx", executableName);
1109 else if(osVersionNo
== lamexp_winver_vista
)
1111 qDebug("Running on Windows Vista or Windows Server 2008.\n"); //lamexp_check_compatibility_mode("CreateRemoteThreadEx", executableName*/);
1113 else if(osVersionNo
== lamexp_winver_win70
)
1115 qDebug("Running on Windows 7 or Windows Server 2008 R2.\n"); //lamexp_check_compatibility_mode("CreateFile2", executableName);
1117 else if(osVersionNo
== lamexp_winver_win80
)
1119 qDebug("Running on Windows 8 or Windows Server 2012.\n"); //lamexp_check_compatibility_mode("FindPackagesByPackageFamily", executableName);
1121 else if(osVersionNo
== lamexp_winver_win81
)
1123 qDebug("Running on Windows 8.1 or Windows Server 2012 R2.\n"); //lamexp_check_compatibility_mode(NULL, executableName);
1127 const QString message
= QString().sprintf("Running on an unknown WindowsNT-based system (v%u.%u).", osVersionNo
.versionMajor
, osVersionNo
.versionMinor
);
1128 qWarning("%s\n", QUTF8(message
));
1129 MessageBoxW(NULL
, QWCHAR(message
), L
"LameXP", MB_OK
| MB_TOPMOST
| MB_ICONWARNING
);
1132 //Check for compat mode
1133 if(osVersionNo
.overrideFlag
&& (osVersionNo
<= lamexp_winver_win81
))
1135 qWarning("Windows compatibility mode detected!");
1136 if(!arguments
.contains("--ignore-compat-mode", Qt::CaseInsensitive
))
1138 qFatal("%s", QApplication::tr("Executable '%1' doesn't support Windows compatibility mode.").arg(executableName
).toLatin1().constData());
1144 if(lamexp_detect_wine())
1146 qWarning("It appears we are running under Wine, unexpected things might happen!\n");
1149 //Set text Codec for locale
1150 QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
1152 //Create Qt application instance
1153 QApplication
*application
= new QApplication(argc
, argv
);
1155 //Load plugins from application directory
1156 QCoreApplication::setLibraryPaths(QStringList() << QApplication::applicationDirPath());
1157 qDebug("Library Path:\n%s\n", QUTF8(QApplication::libraryPaths().first()));
1159 //Set application properties
1160 application
->setApplicationName("LameXP - Audio Encoder Front-End");
1161 application
->setApplicationVersion(QString().sprintf("%d.%02d.%04d", lamexp_version_major(), lamexp_version_minor(), lamexp_version_build()));
1162 application
->setOrganizationName("LoRd_MuldeR");
1163 application
->setOrganizationDomain("mulder.at.gg");
1164 application
->setWindowIcon(lamexp_app_icon());
1165 application
->setEventFilter(lamexp_event_filter
);
1167 //Check for supported image formats
1168 QList
<QByteArray
> supportedFormats
= QImageReader::supportedImageFormats();
1169 for(int i
= 0; g_lamexp_imageformats
[i
]; i
++)
1171 if(!supportedFormats
.contains(g_lamexp_imageformats
[i
]))
1173 qFatal("Qt initialization error: QImageIOHandler for '%s' missing!", g_lamexp_imageformats
[i
]);
1178 //Enable larger/smaller font size
1179 double fontScaleFactor
= 1.0;
1180 if(arguments
.contains("--huge-font", Qt::CaseInsensitive
)) fontScaleFactor
= 1.500;
1181 if(arguments
.contains("--big-font", Qt::CaseInsensitive
)) fontScaleFactor
= 1.250;
1182 if(arguments
.contains("--small-font", Qt::CaseInsensitive
)) fontScaleFactor
= 0.875;
1183 if(arguments
.contains("--tiny-font", Qt::CaseInsensitive
)) fontScaleFactor
= 0.750;
1184 if(!qFuzzyCompare(fontScaleFactor
, 1.0))
1186 qWarning("Application font scale factor set to: %.3f\n", fontScaleFactor
);
1187 QFont appFont
= application
->font();
1188 appFont
.setPointSizeF(appFont
.pointSizeF() * fontScaleFactor
);
1189 application
->setFont(appFont
);
1192 //Add the default translations
1193 lamexp_translation_init();
1195 //Check for process elevation
1196 if(lamexp_process_is_elevated() && (!lamexp_detect_wine()))
1198 QMessageBox
messageBox(QMessageBox::Warning
, "LameXP", "<nobr>LameXP was started with 'elevated' rights, altough LameXP does not need these rights.<br>Running an applications with unnecessary rights is a potential security risk!</nobr>", QMessageBox::NoButton
, NULL
, Qt::Dialog
| Qt::MSWindowsFixedSizeDialogHint
| Qt::WindowStaysOnTopHint
);
1199 messageBox
.addButton("Quit Program (Recommended)", QMessageBox::NoRole
);
1200 messageBox
.addButton("Ignore", QMessageBox::NoRole
);
1201 if(messageBox
.exec() == 0)
1207 //Update console icon, if a console is attached
1208 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
1209 if(g_lamexp_console_attached
&& (!lamexp_detect_wine()))
1211 QLibrary
kernel32("kernel32.dll");
1214 typedef DWORD (__stdcall
*SetConsoleIconFun
)(HICON
);
1215 if(SetConsoleIconFun SetConsoleIconPtr
= (SetConsoleIconFun
) kernel32
.resolve("SetConsoleIcon"))
1217 if(HICON hIcon
= lamexp_qicon2hicon(QIcon(":/icons/sound.png"), 16, 16))
1219 SetConsoleIconPtr(hIcon
);
1228 qt_initialized
= true;
1232 const QStringList
&lamexp_arguments(void)
1234 QReadLocker
readLock(&g_lamexp_argv
.lock
);
1236 if(!g_lamexp_argv
.list
)
1239 QWriteLocker
writeLock(&g_lamexp_argv
.lock
);
1241 g_lamexp_argv
.list
= new QStringList
;
1244 LPWSTR
*szArglist
= CommandLineToArgvW(GetCommandLineW(), &nArgs
);
1246 if(NULL
!= szArglist
)
1248 for(int i
= 0; i
< nArgs
; i
++)
1250 (*g_lamexp_argv
.list
) << WCHAR2QSTR(szArglist
[i
]);
1252 LocalFree(szArglist
);
1256 qWarning("CommandLineToArgvW() has failed !!!");
1260 return (*g_lamexp_argv
.list
);
1264 * Locate known folder on local system
1266 const QString
&lamexp_known_folder(lamexp_known_folder_t folder_id
)
1268 static const int CSIDL_FLAG_CREATE
= 0x8000;
1269 typedef enum { KF_FLAG_CREATE
= 0x00008000 } kf_flags_t
;
1276 static s_folders
[] =
1278 { 0x001c, {0xF1B32785,0x6FBA,0x4FCF,{0x9D,0x55,0x7B,0x8E,0x7F,0x15,0x70,0x91}} }, //CSIDL_LOCAL_APPDATA
1279 { 0x0026, {0x905e63b6,0xc1bf,0x494e,{0xb2,0x9c,0x65,0xb7,0x32,0xd3,0xd2,0x1a}} }, //CSIDL_PROGRAM_FILES
1280 { 0x0024, {0xF38BF404,0x1D43,0x42F2,{0x93,0x05,0x67,0xDE,0x0B,0x28,0xFC,0x23}} }, //CSIDL_WINDOWS_FOLDER
1281 { 0x0025, {0x1AC14E77,0x02E7,0x4E5D,{0xB7,0x44,0x2E,0xB1,0xAE,0x51,0x98,0xB7}} }, //CSIDL_SYSTEM_FOLDER
1284 size_t folderId
= size_t(-1);
1288 case lamexp_folder_localappdata
: folderId
= 0; break;
1289 case lamexp_folder_programfiles
: folderId
= 1; break;
1290 case lamexp_folder_systroot_dir
: folderId
= 2; break;
1291 case lamexp_folder_systemfolder
: folderId
= 3; break;
1294 if(folderId
== size_t(-1))
1296 qWarning("Invalid 'known' folder was requested!");
1297 return *reinterpret_cast<QString
*>(NULL
);
1300 QReadLocker
readLock(&g_lamexp_known_folder
.lock
);
1303 if(g_lamexp_known_folder
.knownFolders
)
1305 if(g_lamexp_known_folder
.knownFolders
->contains(folderId
))
1307 return (*g_lamexp_known_folder
.knownFolders
)[folderId
];
1311 //Obtain write lock to initialize
1313 QWriteLocker
writeLock(&g_lamexp_known_folder
.lock
);
1315 //Still not in cache?
1316 if(g_lamexp_known_folder
.knownFolders
)
1318 if(g_lamexp_known_folder
.knownFolders
->contains(folderId
))
1320 return (*g_lamexp_known_folder
.knownFolders
)[folderId
];
1324 //Initialize on first call
1325 if(!g_lamexp_known_folder
.knownFolders
)
1327 QLibrary
shell32("shell32.dll");
1330 g_lamexp_known_folder
.getFolderPath
= (SHGetFolderPath_t
) shell32
.resolve("SHGetFolderPathW");
1331 g_lamexp_known_folder
.getKnownFolderPath
= (SHGetKnownFolderPath_t
) shell32
.resolve("SHGetKnownFolderPath");
1333 g_lamexp_known_folder
.knownFolders
= new QMap
<size_t, QString
>();
1338 //Now try to get the folder path!
1339 if(g_lamexp_known_folder
.getKnownFolderPath
)
1342 if(g_lamexp_known_folder
.getKnownFolderPath(s_folders
[folderId
].guid
, KF_FLAG_CREATE
, NULL
, &path
) == S_OK
)
1344 //MessageBoxW(0, path, L"SHGetKnownFolderPath", MB_TOPMOST);
1345 QDir folderTemp
= QDir(QDir::fromNativeSeparators(QString::fromUtf16(reinterpret_cast<const unsigned short*>(path
))));
1346 if(folderTemp
.exists())
1348 folderPath
= folderTemp
.canonicalPath();
1350 CoTaskMemFree(path
);
1353 else if(g_lamexp_known_folder
.getFolderPath
)
1355 WCHAR
*path
= new WCHAR
[4096];
1356 if(g_lamexp_known_folder
.getFolderPath(NULL
, s_folders
[folderId
].csidl
| CSIDL_FLAG_CREATE
, NULL
, NULL
, path
) == S_OK
)
1358 //MessageBoxW(0, path, L"SHGetFolderPathW", MB_TOPMOST);
1359 QDir folderTemp
= QDir(QDir::fromNativeSeparators(QString::fromUtf16(reinterpret_cast<const unsigned short*>(path
))));
1360 if(folderTemp
.exists())
1362 folderPath
= folderTemp
.canonicalPath();
1365 LAMEXP_DELETE_ARRAY(path
);
1369 g_lamexp_known_folder
.knownFolders
->insert(folderId
, folderPath
);
1370 return (*g_lamexp_known_folder
.knownFolders
)[folderId
];
1374 * Safely remove a file
1376 bool lamexp_remove_file(const QString
&filename
)
1378 if(!QFileInfo(filename
).exists() || !QFileInfo(filename
).isFile())
1384 if(!QFile::remove(filename
))
1386 static const DWORD attrMask
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_SYSTEM
;
1387 const DWORD attributes
= GetFileAttributesW(QWCHAR(filename
));
1388 if(attributes
& attrMask
)
1390 SetFileAttributesW(QWCHAR(filename
), FILE_ATTRIBUTE_NORMAL
);
1392 if(!QFile::remove(filename
))
1394 qWarning("Could not delete \"%s\"", filename
.toLatin1().constData());
1410 * Check if visual themes are enabled (WinXP and later)
1412 bool lamexp_themes_enabled(void)
1414 typedef int (WINAPI
*IsAppThemedFun
)(void);
1416 QReadLocker
readLock(&g_lamexp_themes_enabled
.lock
);
1417 if(g_lamexp_themes_enabled
.bInitialized
)
1419 return g_lamexp_themes_enabled
.bThemesEnabled
;
1423 QWriteLocker
writeLock(&g_lamexp_themes_enabled
.lock
);
1425 if(!g_lamexp_themes_enabled
.bInitialized
)
1427 g_lamexp_themes_enabled
.bThemesEnabled
= false;
1428 const lamexp_os_version_t
&osVersion
= lamexp_get_os_version();
1429 if(osVersion
>= lamexp_winver_winxp
)
1431 IsAppThemedFun IsAppThemedPtr
= NULL
;
1432 QLibrary
uxTheme(QString("%1/UxTheme.dll").arg(lamexp_known_folder(lamexp_folder_systemfolder
)));
1435 IsAppThemedPtr
= (IsAppThemedFun
) uxTheme
.resolve("IsAppThemed");
1439 g_lamexp_themes_enabled
.bThemesEnabled
= IsAppThemedPtr();
1440 if(!g_lamexp_themes_enabled
.bThemesEnabled
)
1442 qWarning("Theme support is disabled for this process!");
1446 g_lamexp_themes_enabled
.bInitialized
= true;
1449 return g_lamexp_themes_enabled
.bThemesEnabled
;
1453 * Get number of free bytes on disk
1455 unsigned __int64
lamexp_free_diskspace(const QString
&path
, bool *ok
)
1457 ULARGE_INTEGER freeBytesAvailable
, totalNumberOfBytes
, totalNumberOfFreeBytes
;
1458 if(GetDiskFreeSpaceExW(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(path
).utf16()), &freeBytesAvailable
, &totalNumberOfBytes
, &totalNumberOfFreeBytes
))
1461 return freeBytesAvailable
.QuadPart
;
1471 * Check if computer does support hibernation
1473 bool lamexp_is_hibernation_supported(void)
1475 bool hibernationSupported
= false;
1477 SYSTEM_POWER_CAPABILITIES pwrCaps
;
1478 SecureZeroMemory(&pwrCaps
, sizeof(SYSTEM_POWER_CAPABILITIES
));
1480 if(GetPwrCapabilities(&pwrCaps
))
1482 hibernationSupported
= pwrCaps
.SystemS4
&& pwrCaps
.HiberFilePresent
;
1485 return hibernationSupported
;
1489 * Shutdown the computer
1491 bool lamexp_shutdown_computer(const QString
&message
, const unsigned long timeout
, const bool forceShutdown
, const bool hibernate
)
1493 HANDLE hToken
= NULL
;
1495 if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
, &hToken
))
1497 TOKEN_PRIVILEGES privileges
;
1498 memset(&privileges
, 0, sizeof(TOKEN_PRIVILEGES
));
1499 privileges
.PrivilegeCount
= 1;
1500 privileges
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1502 if(LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, &privileges
.Privileges
[0].Luid
))
1504 if(AdjustTokenPrivileges(hToken
, FALSE
, &privileges
, NULL
, NULL
, NULL
))
1508 if(SetSuspendState(TRUE
, TRUE
, TRUE
))
1513 const DWORD reason
= SHTDN_REASON_MAJOR_APPLICATION
| SHTDN_REASON_FLAG_PLANNED
;
1514 return InitiateSystemShutdownEx(NULL
, const_cast<wchar_t*>(QWCHAR(message
)), timeout
, forceShutdown
? TRUE
: FALSE
, FALSE
, reason
);
1523 * Determines the current date, resistant against certain manipulations
1525 QDate
lamexp_current_date_safe(void)
1527 const DWORD MAX_PROC
= 1024;
1528 DWORD
*processes
= new DWORD
[MAX_PROC
];
1529 DWORD bytesReturned
= 0;
1531 if(!EnumProcesses(processes
, sizeof(DWORD
) * MAX_PROC
, &bytesReturned
))
1533 LAMEXP_DELETE_ARRAY(processes
);
1534 return QDate::currentDate();
1537 const DWORD procCount
= bytesReturned
/ sizeof(DWORD
);
1538 ULARGE_INTEGER lastStartTime
;
1539 memset(&lastStartTime
, 0, sizeof(ULARGE_INTEGER
));
1541 for(DWORD i
= 0; i
< procCount
; i
++)
1543 HANDLE hProc
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, processes
[i
]);
1546 FILETIME processTime
[4];
1547 if(GetProcessTimes(hProc
, &processTime
[0], &processTime
[1], &processTime
[2], &processTime
[3]))
1549 ULARGE_INTEGER timeCreation
;
1550 timeCreation
.LowPart
= processTime
[0].dwLowDateTime
;
1551 timeCreation
.HighPart
= processTime
[0].dwHighDateTime
;
1552 if(timeCreation
.QuadPart
> lastStartTime
.QuadPart
)
1554 lastStartTime
.QuadPart
= timeCreation
.QuadPart
;
1561 LAMEXP_DELETE_ARRAY(processes
);
1563 FILETIME lastStartTime_fileTime
;
1564 lastStartTime_fileTime
.dwHighDateTime
= lastStartTime
.HighPart
;
1565 lastStartTime_fileTime
.dwLowDateTime
= lastStartTime
.LowPart
;
1567 FILETIME lastStartTime_localTime
;
1568 if(!FileTimeToLocalFileTime(&lastStartTime_fileTime
, &lastStartTime_localTime
))
1570 memcpy(&lastStartTime_localTime
, &lastStartTime_fileTime
, sizeof(FILETIME
));
1573 SYSTEMTIME lastStartTime_system
;
1574 if(!FileTimeToSystemTime(&lastStartTime_localTime
, &lastStartTime_system
))
1576 memset(&lastStartTime_system
, 0, sizeof(SYSTEMTIME
));
1577 lastStartTime_system
.wYear
= 1970; lastStartTime_system
.wMonth
= lastStartTime_system
.wDay
= 1;
1580 const QDate currentDate
= QDate::currentDate();
1581 const QDate processDate
= QDate(lastStartTime_system
.wYear
, lastStartTime_system
.wMonth
, lastStartTime_system
.wDay
);
1582 return (currentDate
>= processDate
) ? currentDate
: processDate
;
1586 * Show system message box
1588 int lamexp_system_message(const wchar_t *text
, int beepType
)
1590 UINT flags
= MB_OK
| MB_TOPMOST
;
1594 case lamexp_beep_info
: flags
= flags
| MB_ICONASTERISK
;
1595 case lamexp_beep_warning
: flags
= flags
| MB_ICONEXCLAMATION
;
1596 case lamexp_beep_error
: flags
= flags
| MB_ICONHAND
;
1599 return MessageBoxW(NULL
, text
, L
"LameXP", flags
);
1603 * Block window "move" message
1605 bool lamexp_block_window_move(void *message
)
1609 MSG
*msg
= reinterpret_cast<MSG
*>(message
);
1610 if((msg
->message
== WM_SYSCOMMAND
) && (msg
->wParam
== SC_MOVE
))
1614 if((msg
->message
== WM_NCLBUTTONDOWN
) && (msg
->wParam
== HTCAPTION
))
1623 * Suspend calling thread for N milliseconds
1625 inline void lamexp_sleep(const unsigned int delay
)
1630 bool lamexp_beep(int beepType
)
1634 case lamexp_beep_info
: return MessageBeep(MB_ICONASTERISK
) == TRUE
; break;
1635 case lamexp_beep_warning
: return MessageBeep(MB_ICONEXCLAMATION
) == TRUE
; break;
1636 case lamexp_beep_error
: return MessageBeep(MB_ICONHAND
) == TRUE
; break;
1637 default: return false;
1642 * Play a sound (from resources)
1644 bool lamexp_play_sound(const QString
&name
, const bool bAsync
)
1646 const unsigned char *data
= NULL
;
1648 //Try to look-up the sound in the cache first
1651 QReadLocker
readLock(&g_lamexp_sounds
.lock
);
1652 if(g_lamexp_sounds
.sound_db
&& g_lamexp_sounds
.sound_db
->contains(name
))
1654 data
= g_lamexp_sounds
.sound_db
->value(name
);
1658 //If data not found in cache, try to load from resource!
1659 if((!data
) && (!name
.isEmpty()))
1661 QResource
resource(QString(":/sounds/%1.wav").arg(name
));
1662 if(resource
.isValid() && (data
= resource
.data()))
1664 QWriteLocker
writeLock(&g_lamexp_sounds
.lock
);
1665 if(!g_lamexp_sounds
.sound_db
)
1667 g_lamexp_sounds
.sound_db
= new QHash
<const QString
, const unsigned char*>();
1669 g_lamexp_sounds
.sound_db
->insert(name
, data
);
1673 qWarning("Sound effect \"%s\" not found!", QUTF8(name
));
1677 //Play the sound, if availbale
1680 return PlaySound(LPCWSTR(data
), NULL
, (SND_MEMORY
| (bAsync
? SND_ASYNC
: SND_SYNC
))) != FALSE
;
1687 * Play a sound (system alias)
1689 bool lamexp_play_sound_alias(const QString
&alias
, const bool bAsync
)
1691 return PlaySound(QWCHAR(alias
), GetModuleHandle(NULL
), (SND_ALIAS
| (bAsync
? SND_ASYNC
: SND_SYNC
))) != FALSE
;
1695 * Play a sound (from external DLL)
1697 bool lamexp_play_sound_file(const QString
&library
, const unsigned short uiSoundIdx
, const bool bAsync
)
1699 bool result
= false;
1701 QFileInfo
libraryFile(library
);
1702 if(!libraryFile
.isAbsolute())
1704 const QString
&systemDir
= lamexp_known_folder(lamexp_folder_systemfolder
);
1705 if(!systemDir
.isEmpty())
1707 libraryFile
.setFile(QDir(systemDir
), libraryFile
.fileName());
1711 if(libraryFile
.exists() && libraryFile
.isFile())
1713 if(HMODULE module
= LoadLibraryW(QWCHAR(QDir::toNativeSeparators(libraryFile
.canonicalFilePath()))))
1715 result
= (PlaySound(MAKEINTRESOURCE(uiSoundIdx
), module
, (SND_RESOURCE
| (bAsync
? SND_ASYNC
: SND_SYNC
))) != FALSE
);
1716 FreeLibrary(module
);
1721 qWarning("PlaySound: File \"%s\" could not be found!", QUTF8(libraryFile
.absoluteFilePath()));
1728 * Open file using the shell
1730 bool lamexp_exec_shell(const QWidget
*win
, const QString
&url
, const bool explore
)
1732 return lamexp_exec_shell(win
, url
, QString(), QString(), explore
);
1736 * Open file using the shell (with parameters)
1738 bool lamexp_exec_shell(const QWidget
*win
, const QString
&url
, const QString
¶meters
, const QString
&directory
, const bool explore
)
1740 return ((int) ShellExecuteW(((win
) ? win
->winId() : NULL
), (explore
? L
"explore" : L
"open"), QWCHAR(url
), ((!parameters
.isEmpty()) ? QWCHAR(parameters
) : NULL
), ((!directory
.isEmpty()) ? QWCHAR(directory
) : NULL
), SW_SHOW
)) > 32;
1744 * Query value of the performance counter
1746 __int64
lamexp_perfcounter_value(void)
1748 LARGE_INTEGER counter
;
1749 if(QueryPerformanceCounter(&counter
) == TRUE
)
1751 return counter
.QuadPart
;
1757 * Query frequency of the performance counter
1759 __int64
lamexp_perfcounter_frequ(void)
1761 LARGE_INTEGER frequency
;
1762 if(QueryPerformanceFrequency(&frequency
) == TRUE
)
1764 return frequency
.QuadPart
;
1770 * Insert entry to the window's system menu
1772 bool lamexp_append_sysmenu(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
1776 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
1778 ok
= (AppendMenuW(hMenu
, MF_SEPARATOR
, 0, 0) == TRUE
);
1779 ok
= (AppendMenuW(hMenu
, MF_STRING
, identifier
, QWCHAR(text
)) == TRUE
);
1786 * Insert entry to the window's system menu
1788 bool lamexp_check_sysmenu_msg(void *message
, const unsigned int identifier
)
1790 return (((MSG
*)message
)->message
== WM_SYSCOMMAND
) && ((((MSG
*)message
)->wParam
& 0xFFF0) == identifier
);
1794 * Update system menu entry
1796 bool lamexp_update_sysmenu(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
1800 if(HMENU hMenu
= ::GetSystemMenu(win
->winId(), FALSE
))
1802 ok
= (ModifyMenu(hMenu
, identifier
, MF_STRING
| MF_BYCOMMAND
, identifier
, QWCHAR(text
)) == TRUE
);
1808 * Display the window's close button
1810 bool lamexp_enable_close_button(const QWidget
*win
, const bool bEnable
)
1814 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
1816 ok
= (EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
| (bEnable
? MF_ENABLED
: MF_GRAYED
)) == TRUE
);
1823 * Check whether ESC key has been pressed since the previous call to this function
1825 bool lamexp_check_escape_state(void)
1827 return (GetAsyncKeyState(VK_ESCAPE
) & 0x0001) != 0;
1831 * Set the process priority class for current process
1833 bool lamexp_change_process_priority(const int priority
)
1835 return lamexp_change_process_priority(GetCurrentProcess(), priority
);
1839 * Set the process priority class for specified process
1841 bool lamexp_change_process_priority(const QProcess
*proc
, const int priority
)
1843 if(Q_PID qPid
= proc
->pid())
1845 return lamexp_change_process_priority(qPid
->hProcess
, priority
);
1854 * Set the process priority class for specified process
1856 bool lamexp_change_process_priority(void *hProcess
, const int priority
)
1860 switch(qBound(-2, priority
, 2))
1863 ok
= (SetPriorityClass(hProcess
, HIGH_PRIORITY_CLASS
) == TRUE
);
1866 if(!(ok
= (SetPriorityClass(hProcess
, ABOVE_NORMAL_PRIORITY_CLASS
) == TRUE
)))
1868 ok
= (SetPriorityClass(hProcess
, HIGH_PRIORITY_CLASS
) == TRUE
);
1872 ok
= (SetPriorityClass(hProcess
, NORMAL_PRIORITY_CLASS
) == TRUE
);
1875 if(!(ok
= (SetPriorityClass(hProcess
, BELOW_NORMAL_PRIORITY_CLASS
) == TRUE
)))
1877 ok
= (SetPriorityClass(hProcess
, IDLE_PRIORITY_CLASS
) == TRUE
);
1881 ok
= (SetPriorityClass(hProcess
, IDLE_PRIORITY_CLASS
) == TRUE
);
1889 * Returns the current file time
1891 unsigned __int64
lamexp_current_file_time(void)
1894 GetSystemTimeAsFileTime(&fileTime
);
1896 ULARGE_INTEGER temp
;
1897 temp
.HighPart
= fileTime
.dwHighDateTime
;
1898 temp
.LowPart
= fileTime
.dwLowDateTime
;
1900 return temp
.QuadPart
;
1904 * Bring the specifed window to the front
1906 bool lamexp_bring_to_front(const QWidget
*window
)
1912 for(int i
= 0; (i
< 5) && (!ret
); i
++)
1914 ret
= (SetForegroundWindow(window
->winId()) != FALSE
);
1915 SwitchToThisWindow(window
->winId(), TRUE
);
1917 LockSetForegroundWindow(LSFW_LOCK
);
1924 * Bring window of the specifed process to the front (callback)
1926 static BOOL CALLBACK
lamexp_bring_process_to_front_helper(HWND hwnd
, LPARAM lParam
)
1928 DWORD processId
= *reinterpret_cast<WORD
*>(lParam
);
1929 DWORD windowProcessId
= NULL
;
1930 GetWindowThreadProcessId(hwnd
, &windowProcessId
);
1931 if(windowProcessId
== processId
)
1933 SwitchToThisWindow(hwnd
, TRUE
);
1934 SetForegroundWindow(hwnd
);
1942 * Bring window of the specifed process to the front
1944 bool lamexp_bring_process_to_front(const unsigned long pid
)
1946 return EnumWindows(lamexp_bring_process_to_front_helper
, reinterpret_cast<LPARAM
>(&pid
)) == TRUE
;
1950 * Check the network connectivity status
1952 int lamexp_network_status(void)
1955 const BOOL ret
= IsNetworkAlive(&dwFlags
);
1956 if(GetLastError() == 0)
1958 return (ret
!= FALSE
) ? lamexp_network_yes
: lamexp_network_non
;
1960 return lamexp_network_err
;
1964 * Retrun the process ID of the given QProcess
1966 unsigned long lamexp_process_id(const QProcess
*proc
)
1968 PROCESS_INFORMATION
*procInf
= proc
->pid();
1969 return (procInf
) ? procInf
->dwProcessId
: NULL
;
1973 * Convert long path to short path
1975 QString
lamexp_path_to_short(const QString
&longPath
)
1978 DWORD buffSize
= GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath
.utf16()), NULL
, NULL
);
1982 wchar_t *buffer
= new wchar_t[buffSize
];
1983 DWORD result
= GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath
.utf16()), buffer
, buffSize
);
1985 if(result
> 0 && result
< buffSize
)
1987 shortPath
= QString::fromUtf16(reinterpret_cast<const unsigned short*>(buffer
));
1993 return (shortPath
.isEmpty() ? longPath
: shortPath
);
1997 * Open media file in external player
1999 bool lamexp_open_media_file(const QString
&mediaFilePath
)
2001 const static wchar_t *registryPrefix
[2] = { L
"SOFTWARE\\", L
"SOFTWARE\\Wow6432Node\\" };
2002 const static wchar_t *registryKeys
[3] =
2004 L
"Microsoft\\Windows\\CurrentVersion\\Uninstall\\{97D341C8-B0D1-4E4A-A49A-C30B52F168E9}",
2005 L
"Microsoft\\Windows\\CurrentVersion\\Uninstall\\{DB9E4EAB-2717-499F-8D56-4CC8A644AB60}",
2008 const static wchar_t *appNames
[4] = { L
"smplayer_portable.exe", L
"smplayer.exe", L
"MPUI.exe", L
"foobar2000.exe" };
2009 const static wchar_t *valueNames
[2] = { L
"InstallLocation", L
"InstallDir" };
2011 for(size_t i
= 0; i
< 3; i
++)
2013 for(size_t j
= 0; j
< 2; j
++)
2015 QString mplayerPath
;
2016 HKEY registryKeyHandle
= NULL
;
2018 const QString currentKey
= WCHAR2QSTR(registryPrefix
[j
]).append(WCHAR2QSTR(registryKeys
[i
]));
2019 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE
, QWCHAR(currentKey
), 0, KEY_READ
, ®istryKeyHandle
) == ERROR_SUCCESS
)
2021 for(size_t k
= 0; k
< 2; k
++)
2023 wchar_t Buffer
[4096];
2024 DWORD BuffSize
= sizeof(wchar_t*) * 4096;
2025 DWORD DataType
= REG_NONE
;
2026 if(RegQueryValueExW(registryKeyHandle
, valueNames
[k
], 0, &DataType
, reinterpret_cast<BYTE
*>(Buffer
), &BuffSize
) == ERROR_SUCCESS
)
2028 if((DataType
== REG_SZ
) || (DataType
== REG_EXPAND_SZ
) || (DataType
== REG_LINK
))
2030 mplayerPath
= WCHAR2QSTR(Buffer
);
2035 RegCloseKey(registryKeyHandle
);
2038 if(!mplayerPath
.isEmpty())
2040 QDir
mplayerDir(mplayerPath
);
2041 if(mplayerDir
.exists())
2043 for(size_t k
= 0; k
< 4; k
++)
2045 if(mplayerDir
.exists(WCHAR2QSTR(appNames
[k
])))
2047 qDebug("Player found at:\n%s\n", QUTF8(mplayerDir
.absoluteFilePath(WCHAR2QSTR(appNames
[k
]))));
2048 QProcess::startDetached(mplayerDir
.absoluteFilePath(WCHAR2QSTR(appNames
[k
])), QStringList() << QDir::toNativeSeparators(mediaFilePath
));
2059 static void lamexp_init_dwmapi(void)
2061 QReadLocker
writeLock(&g_lamexp_dwmapi
.lock
);
2063 //Not initialized yet?
2064 if(g_lamexp_dwmapi
.bInitialized
)
2069 //Reset function pointers
2070 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= NULL
;
2071 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= NULL
;
2072 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= NULL
;
2074 //Does OS support DWM?
2075 if(lamexp_get_os_version() >= lamexp_winver_vista
)
2078 g_lamexp_dwmapi
.dwmapi_dll
= new QLibrary("dwmapi.dll");
2079 if(g_lamexp_dwmapi
.dwmapi_dll
->load())
2081 //Initialize function pointers
2082 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= (HRESULT (__stdcall
*)(BOOL
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmIsCompositionEnabled");
2083 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= (HRESULT (__stdcall
*)(HWND
, const MARGINS
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmExtendFrameIntoClientArea");
2084 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= (HRESULT (__stdcall
*)(HWND
, const DWM_BLURBEHIND
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmEnableBlurBehindWindow");
2088 LAMEXP_DELETE(g_lamexp_dwmapi
.dwmapi_dll
);
2089 qWarning("Failed to load DWMAPI.DLL on a DWM-enabled system!");
2093 g_lamexp_dwmapi
.bInitialized
= true;
2097 * Enable "sheet of glass" effect on the given Window
2099 bool lamexp_sheet_of_glass(QWidget
*window
)
2101 QReadLocker
readLock(&g_lamexp_dwmapi
.lock
);
2103 //Initialize the DWM API
2104 while(!g_lamexp_dwmapi
.bInitialized
)
2107 lamexp_init_dwmapi();
2111 BOOL bCompositionEnabled
= FALSE
;
2113 //Required functions available?
2114 if((g_lamexp_dwmapi
.dwmIsCompositionEnabled
!= NULL
) && (g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
!= NULL
) && (g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
!= NULL
))
2116 //Check if composition is currently enabled
2117 if(HRESULT hr
= g_lamexp_dwmapi
.dwmIsCompositionEnabled(&bCompositionEnabled
))
2119 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
2124 //All functions available *and* composition enabled?
2125 if(!bCompositionEnabled
)
2130 //Enable the "sheet of glass" effect on this window
2131 MARGINS margins
= {-1, -1, -1, -1};
2132 if(HRESULT hr
= g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea(window
->winId(), &margins
))
2134 qWarning("DwmExtendFrameIntoClientArea function has failed! (error %d)", hr
);
2138 //Create and populate the Blur Behind structure
2140 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
2142 bb
.dwFlags
= DWM_BB_ENABLE
;
2143 if(HRESULT hr
= g_lamexp_dwmapi
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
2145 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
2150 window
->setAutoFillBackground(false);
2151 window
->setAttribute(Qt::WA_TranslucentBackground
);
2152 window
->setAttribute(Qt::WA_NoSystemBackground
);
2158 * Update "sheet of glass" effect on the given Window
2160 bool lamexp_sheet_of_glass_update(QWidget
*window
)
2162 QReadLocker
readLock(&g_lamexp_dwmapi
.lock
);
2164 //Initialize the DWM API
2165 while(!g_lamexp_dwmapi
.bInitialized
)
2168 lamexp_init_dwmapi();
2172 BOOL bCompositionEnabled
= FALSE
;
2174 //Required functions available?
2175 if((g_lamexp_dwmapi
.dwmIsCompositionEnabled
!= NULL
) && (g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
!= NULL
))
2177 //Check if composition is currently enabled
2178 if(HRESULT hr
= g_lamexp_dwmapi
.dwmIsCompositionEnabled(&bCompositionEnabled
))
2180 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
2185 //All functions available *and* composition enabled?
2186 if(!bCompositionEnabled
)
2191 //Create and populate the Blur Behind structure
2193 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
2195 bb
.dwFlags
= DWM_BB_ENABLE
;
2196 if(HRESULT hr
= g_lamexp_dwmapi
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
2198 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
2206 * Update the window icon
2208 lamexp_icon_t
*lamexp_set_window_icon(QWidget
*window
, const QIcon
&icon
, const bool bIsBigIcon
)
2212 const int extend
= (bIsBigIcon
? 32 : 16);
2213 if(HICON hIcon
= lamexp_qicon2hicon(icon
, extend
, extend
))
2215 SendMessage(window
->winId(), WM_SETICON
, (bIsBigIcon
? ICON_BIG
: ICON_SMALL
), LPARAM(hIcon
));
2216 return reinterpret_cast<lamexp_icon_t
*>(hIcon
);
2225 void lamexp_free_window_icon(lamexp_icon_t
*icon
)
2227 if(HICON hIcon
= reinterpret_cast<HICON
>(icon
))
2234 * Get system color info
2236 QColor
lamexp_system_color(const int color_id
)
2242 case lamexp_syscolor_text
:
2243 nIndex
= COLOR_WINDOWTEXT
; /*Text in windows*/
2245 case lamexp_syscolor_background
:
2246 nIndex
= COLOR_WINDOW
; /*Window background*/
2248 case lamexp_syscolor_caption
:
2249 nIndex
= COLOR_CAPTIONTEXT
; /*Text in caption, size box, and scroll bar arrow box*/
2252 qWarning("Unknown system color id (%d) specified!", color_id
);
2253 nIndex
= COLOR_WINDOWTEXT
;
2256 const DWORD rgb
= GetSysColor(nIndex
);
2257 QColor
color(GetRValue(rgb
), GetGValue(rgb
), GetBValue(rgb
));
2262 * Check if the current user is an administartor (helper function)
2264 static bool lamexp_user_is_admin_helper(void)
2266 HANDLE hToken
= NULL
;
2267 if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
2273 if(!GetTokenInformation(hToken
, TokenGroups
, NULL
, 0, &dwSize
))
2275 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2277 CloseHandle(hToken
);
2282 PTOKEN_GROUPS lpGroups
= (PTOKEN_GROUPS
) malloc(dwSize
);
2285 CloseHandle(hToken
);
2289 if(!GetTokenInformation(hToken
, TokenGroups
, lpGroups
, dwSize
, &dwSize
))
2292 CloseHandle(hToken
);
2296 PSID lpSid
= NULL
; SID_IDENTIFIER_AUTHORITY Authority
= {SECURITY_NT_AUTHORITY
};
2297 if(!AllocateAndInitializeSid(&Authority
, 2, SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
, 0, 0, 0, 0, 0, 0, &lpSid
))
2300 CloseHandle(hToken
);
2304 bool bResult
= false;
2305 for(DWORD i
= 0; i
< lpGroups
->GroupCount
; i
++)
2307 if(EqualSid(lpSid
, lpGroups
->Groups
[i
].Sid
))
2316 CloseHandle(hToken
);
2321 * Check if the current user is an administartor
2323 bool lamexp_user_is_admin(void)
2325 bool isAdmin
= false;
2327 //Check for process elevation and UAC support first!
2328 if(lamexp_process_is_elevated(&isAdmin
))
2330 qWarning("Process is elevated -> user is admin!");
2334 //If not elevated and UAC is not available -> user must be in admin group!
2337 qDebug("UAC is disabled/unavailable -> checking for Administrators group");
2338 isAdmin
= lamexp_user_is_admin_helper();
2345 * Check if file is a valid Win32/Win64 executable
2347 bool lamexp_is_executable(const QString
&path
)
2349 bool bIsExecutable
= false;
2351 if(GetBinaryType(QWCHAR(QDir::toNativeSeparators(path
)), &binaryType
))
2353 bIsExecutable
= (binaryType
== SCS_32BIT_BINARY
|| binaryType
== SCS_64BIT_BINARY
);
2355 return bIsExecutable
;
2359 * Fatal application exit - helper
2361 static DWORD WINAPI
lamexp_fatal_exit_helper(LPVOID lpParameter
)
2363 MessageBoxA(NULL
, ((LPCSTR
) lpParameter
), "LameXP - Guru Meditation", MB_OK
| MB_ICONERROR
| MB_TASKMODAL
| MB_TOPMOST
| MB_SETFOREGROUND
);
2368 * Fatal application exit
2370 void lamexp_fatal_exit(const char* const errorMessage
)
2372 g_lamexp_fatal_lock
.enter();
2374 if(!g_lamexp_fatal_flag
)
2376 return; /*prevent recursive invocation*/
2379 g_lamexp_fatal_flag
= false;
2381 if(g_main_thread_id
!= GetCurrentThreadId())
2383 if(HANDLE hThreadMain
= OpenThread(THREAD_SUSPEND_RESUME
, FALSE
, g_main_thread_id
))
2385 SuspendThread(hThreadMain
); /*stop main thread*/
2389 if(HANDLE hThread
= CreateThread(NULL
, 0, lamexp_fatal_exit_helper
, (LPVOID
) errorMessage
, 0, NULL
))
2391 WaitForSingleObject(hThread
, INFINITE
);
2396 TerminateProcess(GetCurrentProcess(), 666);
2401 * Initialize debug thread
2403 static const HANDLE g_debug_thread1
= LAMEXP_DEBUG
? NULL
: lamexp_debug_thread_init();
2406 * Get number private bytes [debug only]
2408 unsigned long lamexp_dbg_private_bytes(void)
2411 for(int i
= 0; i
< 8; i
++) _heapmin();
2412 PROCESS_MEMORY_COUNTERS_EX memoryCounters
;
2413 memoryCounters
.cb
= sizeof(PROCESS_MEMORY_COUNTERS_EX
);
2414 GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS
) &memoryCounters
, sizeof(PROCESS_MEMORY_COUNTERS_EX
));
2415 return memoryCounters
.PrivateUsage
;
2417 THROW("Cannot call this function in a non-debug build!");
2418 #endif //LAMEXP_DEBUG
2422 * Output string to debugger [debug only]
2424 void lamexp_dbg_dbg_output_string(const char* format
, ...)
2429 va_start (args
, format
);
2430 vsnprintf_s(buffer
, 256, _TRUNCATE
, format
, args
);
2431 OutputDebugStringA(buffer
);
2434 THROW("Cannot call this function in a non-debug build!");
2435 #endif //LAMEXP_DEBUG
2438 ///////////////////////////////////////////////////////////////////////////////
2440 ///////////////////////////////////////////////////////////////////////////////
2442 extern "C" void _lamexp_global_init_win32(void)
2444 if((!LAMEXP_DEBUG
) && lamexp_check_for_debugger())
2446 lamexp_fatal_exit("Not a debug build. Please unload debugger and try again!");
2449 //Zero *before* constructors are called
2450 LAMEXP_ZERO_MEMORY(g_lamexp_argv
);
2451 LAMEXP_ZERO_MEMORY(g_lamexp_known_folder
);
2452 LAMEXP_ZERO_MEMORY(g_lamexp_os_version
);
2453 LAMEXP_ZERO_MEMORY(g_lamexp_wine
);
2454 LAMEXP_ZERO_MEMORY(g_lamexp_themes_enabled
);
2455 LAMEXP_ZERO_MEMORY(g_lamexp_dwmapi
);
2456 LAMEXP_ZERO_MEMORY(g_lamexp_sounds
);
2459 ///////////////////////////////////////////////////////////////////////////////
2461 ///////////////////////////////////////////////////////////////////////////////
2463 extern "C" void _lamexp_global_free_win32(void)
2465 //Clear folder cache
2466 LAMEXP_DELETE(g_lamexp_known_folder
.knownFolders
);
2468 //Destroy Qt application object
2469 QApplication
*application
= dynamic_cast<QApplication
*>(QApplication::instance());
2470 LAMEXP_DELETE(application
);
2473 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= NULL
;
2474 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= NULL
;
2475 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= NULL
;
2476 LAMEXP_DELETE(g_lamexp_dwmapi
.dwmapi_dll
);
2478 //Free STDOUT and STDERR buffers
2479 if(g_lamexp_console_attached
)
2481 if(std::filebuf
*tmp
= dynamic_cast<std::filebuf
*>(std::cout
.rdbuf()))
2483 std::cout
.rdbuf(NULL
);
2486 if(std::filebuf
*tmp
= dynamic_cast<std::filebuf
*>(std::cerr
.rdbuf()))
2488 std::cerr
.rdbuf(NULL
);
2494 if(g_lamexp_log_file
)
2496 fclose(g_lamexp_log_file
);
2497 g_lamexp_log_file
= NULL
;
2501 LAMEXP_DELETE(g_lamexp_sounds
.sound_db
);
2503 //Free CLI Arguments
2504 LAMEXP_DELETE(g_lamexp_argv
.list
);