1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
25 #include <MUtils/Global.h>
26 #include <MUtils/OSSupport.h>
27 #include "CriticalSection_Win32.h"
30 #define WIN32_LEAN_AND_MEAN 1
37 #include <QReadWriteLock>
42 static const DWORD g_main_thread_id
= GetCurrentThreadId();
44 ///////////////////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////////////////
48 typedef HRESULT (WINAPI
*SHGetKnownFolderPath_t
)(const GUID
&rfid
, DWORD dwFlags
, HANDLE hToken
, PWSTR
*ppszPath
);
49 typedef HRESULT (WINAPI
*SHGetFolderPath_t
)(HWND hwndOwner
, int nFolder
, HANDLE hToken
, DWORD dwFlags
, LPWSTR pszPath
);
51 static QMap
<size_t, QString
>* g_known_folders_map
;
52 static SHGetKnownFolderPath_t g_known_folders_fpGetKnownFolderPath
;
53 static SHGetFolderPath_t g_known_folders_fpGetFolderPath
;
54 static QReadWriteLock g_known_folders_lock
;
56 const QString
&MUtils::OS::known_folder(known_folder_t folder_id
)
58 static const int CSIDL_FLAG_CREATE
= 0x8000;
59 typedef enum { KF_FLAG_CREATE
= 0x00008000 } kf_flags_t
;
68 { 0x001c, {0xF1B32785,0x6FBA,0x4FCF,{0x9D,0x55,0x7B,0x8E,0x7F,0x15,0x70,0x91}} }, //CSIDL_LOCAL_APPDATA
69 { 0x0026, {0x905e63b6,0xc1bf,0x494e,{0xb2,0x9c,0x65,0xb7,0x32,0xd3,0xd2,0x1a}} }, //CSIDL_PROGRAM_FILES
70 { 0x0024, {0xF38BF404,0x1D43,0x42F2,{0x93,0x05,0x67,0xDE,0x0B,0x28,0xFC,0x23}} }, //CSIDL_WINDOWS_FOLDER
71 { 0x0025, {0x1AC14E77,0x02E7,0x4E5D,{0xB7,0x44,0x2E,0xB1,0xAE,0x51,0x98,0xB7}} }, //CSIDL_SYSTEM_FOLDER
74 size_t folderId
= size_t(-1);
78 case FOLDER_LOCALAPPDATA
: folderId
= 0; break;
79 case FOLDER_PROGRAMFILES
: folderId
= 1; break;
80 case FOLDER_SYSTROOT_DIR
: folderId
= 2; break;
81 case FOLDER_SYSTEMFOLDER
: folderId
= 3; break;
84 if(folderId
== size_t(-1))
86 qWarning("Invalid 'known' folder was requested!");
87 return *reinterpret_cast<QString
*>(NULL
);
90 QReadLocker
readLock(&g_known_folders_lock
);
93 if(g_known_folders_map
)
95 if(g_known_folders_map
->contains(folderId
))
97 return g_known_folders_map
->operator[](folderId
);
101 //Obtain write lock to initialize
103 QWriteLocker
writeLock(&g_known_folders_lock
);
105 //Still not in cache?
106 if(g_known_folders_map
)
108 if(g_known_folders_map
->contains(folderId
))
110 return g_known_folders_map
->operator[](folderId
);
114 //Initialize on first call
115 if(!g_known_folders_map
)
117 QLibrary
shell32("shell32.dll");
120 g_known_folders_fpGetFolderPath
= (SHGetFolderPath_t
) shell32
.resolve("SHGetFolderPathW");
121 g_known_folders_fpGetKnownFolderPath
= (SHGetKnownFolderPath_t
) shell32
.resolve("SHGetKnownFolderPath");
123 g_known_folders_map
= new QMap
<size_t, QString
>();
128 //Now try to get the folder path!
129 if(g_known_folders_fpGetKnownFolderPath
)
132 if(g_known_folders_fpGetKnownFolderPath(s_folders
[folderId
].guid
, KF_FLAG_CREATE
, NULL
, &path
) == S_OK
)
134 //MessageBoxW(0, path, L"SHGetKnownFolderPath", MB_TOPMOST);
135 QDir folderTemp
= QDir(QDir::fromNativeSeparators(MUTILS_WCHAR2QSTR(path
)));
136 if(folderTemp
.exists())
138 folderPath
= folderTemp
.canonicalPath();
143 else if(g_known_folders_fpGetFolderPath
)
145 QScopedArrayPointer
<WCHAR
> path(new WCHAR
[4096]);
146 if(g_known_folders_fpGetFolderPath(NULL
, s_folders
[folderId
].csidl
| CSIDL_FLAG_CREATE
, NULL
, NULL
, path
.data()) == S_OK
)
148 //MessageBoxW(0, path, L"SHGetFolderPathW", MB_TOPMOST);
149 QDir folderTemp
= QDir(QDir::fromNativeSeparators(MUTILS_WCHAR2QSTR(path
.data())));
150 if(folderTemp
.exists())
152 folderPath
= folderTemp
.canonicalPath();
158 g_known_folders_map
->insert(folderId
, folderPath
);
159 return g_known_folders_map
->operator[](folderId
);
162 ///////////////////////////////////////////////////////////////////////////////
163 // CURRENT DATA (SAFE)
164 ///////////////////////////////////////////////////////////////////////////////
166 QDate
MUtils::OS::current_date(void)
168 const DWORD MAX_PROC
= 1024;
169 QScopedArrayPointer
<DWORD
> processes(new DWORD
[MAX_PROC
]);
170 DWORD bytesReturned
= 0;
172 if(!EnumProcesses(processes
.data(), sizeof(DWORD
) * MAX_PROC
, &bytesReturned
))
174 return QDate::currentDate();
177 const DWORD procCount
= bytesReturned
/ sizeof(DWORD
);
178 ULARGE_INTEGER lastStartTime
;
179 memset(&lastStartTime
, 0, sizeof(ULARGE_INTEGER
));
181 for(DWORD i
= 0; i
< procCount
; i
++)
183 if(HANDLE hProc
= OpenProcess(PROCESS_QUERY_INFORMATION
, FALSE
, processes
[i
]))
185 FILETIME processTime
[4];
186 if(GetProcessTimes(hProc
, &processTime
[0], &processTime
[1], &processTime
[2], &processTime
[3]))
188 ULARGE_INTEGER timeCreation
;
189 timeCreation
.LowPart
= processTime
[0].dwLowDateTime
;
190 timeCreation
.HighPart
= processTime
[0].dwHighDateTime
;
191 if(timeCreation
.QuadPart
> lastStartTime
.QuadPart
)
193 lastStartTime
.QuadPart
= timeCreation
.QuadPart
;
200 FILETIME lastStartTime_fileTime
;
201 lastStartTime_fileTime
.dwHighDateTime
= lastStartTime
.HighPart
;
202 lastStartTime_fileTime
.dwLowDateTime
= lastStartTime
.LowPart
;
204 FILETIME lastStartTime_localTime
;
205 if(!FileTimeToLocalFileTime(&lastStartTime_fileTime
, &lastStartTime_localTime
))
207 memcpy(&lastStartTime_localTime
, &lastStartTime_fileTime
, sizeof(FILETIME
));
210 SYSTEMTIME lastStartTime_system
;
211 if(!FileTimeToSystemTime(&lastStartTime_localTime
, &lastStartTime_system
))
213 memset(&lastStartTime_system
, 0, sizeof(SYSTEMTIME
));
214 lastStartTime_system
.wYear
= 1970; lastStartTime_system
.wMonth
= lastStartTime_system
.wDay
= 1;
217 const QDate currentDate
= QDate::currentDate();
218 const QDate processDate
= QDate(lastStartTime_system
.wYear
, lastStartTime_system
.wMonth
, lastStartTime_system
.wDay
);
219 return (currentDate
>= processDate
) ? currentDate
: processDate
;
222 ///////////////////////////////////////////////////////////////////////////////
224 ///////////////////////////////////////////////////////////////////////////////
226 static CriticalSection g_fatal_exit_lock
;
227 static volatile bool g_fatal_exit_flag
= true;
229 static DWORD WINAPI
fatal_exit_helper(LPVOID lpParameter
)
231 MessageBoxA(NULL
, ((LPCSTR
) lpParameter
), "LameXP - Guru Meditation", MB_OK
| MB_ICONERROR
| MB_TASKMODAL
| MB_TOPMOST
| MB_SETFOREGROUND
);
235 void MUtils::OS::fatal_exit(const char* const errorMessage
)
237 g_fatal_exit_lock
.enter();
239 if(!g_fatal_exit_flag
)
241 return; /*prevent recursive invocation*/
244 g_fatal_exit_flag
= false;
246 if(g_main_thread_id
!= GetCurrentThreadId())
248 if(HANDLE hThreadMain
= OpenThread(THREAD_SUSPEND_RESUME
, FALSE
, g_main_thread_id
))
250 SuspendThread(hThreadMain
); /*stop main thread*/
254 if(HANDLE hThread
= CreateThread(NULL
, 0, fatal_exit_helper
, (LPVOID
) errorMessage
, 0, NULL
))
256 WaitForSingleObject(hThread
, INFINITE
);
261 TerminateProcess(GetCurrentProcess(), 666);
265 ///////////////////////////////////////////////////////////////////////////////