1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Mayaqua Kernel
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 // Contributors:
18 // - nattoheaven (https://github.com/nattoheaven)
19 //
20 // License: The Apache License, Version 2.0
21 // https://www.apache.org/licenses/LICENSE-2.0
22 //
23 // DISCLAIMER
24 // ==========
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 // SOFTWARE.
33 //
34 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
35 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
36 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
37 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
38 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
39 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
40 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
41 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
42 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
43 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
44 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
45 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
46 // LAW OR COURT RULE.
47 //
48 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
49 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
50 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
51 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
52 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
53 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
54 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
55 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
56 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
57 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
58 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
59 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
60 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
61 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
62 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
63 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
64 // STATEMENT FOR WARNING AND DISCLAIMER.
65 //
66 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
67 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
68 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
69 //
70 //
71 // SOURCE CODE CONTRIBUTION
72 // ------------------------
73 //
74 // Your contribution to SoftEther VPN Project is much appreciated.
75 // Please send patches to us through GitHub.
76 // Read the SoftEther VPN Patch Acceptance Policy in advance:
77 // http://www.softether.org/5-download/src/9.patch
78 //
79 //
80 // DEAR SECURITY EXPERTS
81 // ---------------------
82 //
83 // If you find a bug or a security vulnerability please kindly inform us
84 // about the problem immediately so that we can fix the security problem
85 // to protect a lot of users around the world as soon as possible.
86 //
87 // Our e-mail address for security reports is:
88 // softether-vpn-security [at] softether.org
89 //
90 // Please note that the above e-mail address is not a technical support
91 // inquiry address. If you need technical assistance, please visit
92 // http://www.softether.org/ and ask your question on the users forum.
93 //
94 // Thank you for your cooperation.
95 //
96 //
97 // NO MEMORY OR RESOURCE LEAKS
98 // ---------------------------
99 //
100 // The memory-leaks and resource-leaks verification under the stress
101 // test has been passed before release this source code.
102 
103 
104 // Kernel.c
105 // System service processing routine
106 
107 #include <GlobalConst.h>
108 
109 #include <stdio.h>
110 #include <stdlib.h>
111 #include <string.h>
112 #include <wchar.h>
113 #include <stdarg.h>
114 #include <time.h>
115 #include <errno.h>
116 #include <Mayaqua/Mayaqua.h>
117 
118 #ifndef TM_YEAR_MAX
119 #define TM_YEAR_MAX         2106
120 #endif
121 #ifndef TM_MON_MAX
122 #define TM_MON_MAX          1
123 #endif
124 #ifndef TM_MDAY_MAX
125 #define TM_MDAY_MAX         7
126 #endif
127 #ifndef TM_HOUR_MAX
128 #define TM_HOUR_MAX         6
129 #endif
130 #ifndef TM_MIN_MAX
131 #define TM_MIN_MAX          28
132 #endif
133 #ifndef TM_SEC_MAX
134 #define TM_SEC_MAX          14
135 #endif
136 
137 #define ADJUST_TM(tm_member, tm_carry, modulus) \
138 	if ((tm_member) < 0){ \
139 	tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
140 	tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
141 	} else if ((tm_member) >= (modulus)) { \
142 	tm_carry += (tm_member) / (modulus); \
143 	tm_member = (tm_member) % (modulus); \
144 	}
145 #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
146 #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
147 #define leapday(m, y) ((m) == 1 && leap (y))
148 #define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
149 static int ydays[] =
150 {
151 	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
152 };
153 
154 static UINT current_num_thread = 0;
155 static UINT cached_number_of_cpus = 0;
156 
157 
158 
159 static wchar_t *default_locale_str =
160 L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
161 
162 
163 static LOCALE current_locale;
164 LOCK *tick_manual_lock = NULL;
165 UINT g_zero = 0;
166 
167 #define MONSPERYEAR 12
168 #define DAYSPERNYEAR 365
169 #define DAYSPERLYEAR 366
170 #define SECSPERMIN 60
171 #define SECSPERHOUR (60*60)
172 #define SECSPERDAY (24*60*60)
173 #define DAYSPERWEEK 7
174 #define TM_SUNDAY	0
175 #define TM_MONDAY	1
176 #define TM_TUESDAY	2
177 #define TM_WEDNESDAY	3
178 #define TM_THURSDAY	4
179 #define TM_FRIDAY	5
180 #define TM_SATURDAY	6
181 
182 #define TM_YEAR_BASE	1900
183 
184 #define EPOCH_YEAR	1970
185 #define EPOCH_WDAY	TM_THURSDAY
186 
187 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
188 
189 static const int	mon_lengths[2][MONSPERYEAR] = {
190 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
191 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
192 };
193 
194 static const int	year_lengths[2] = {
195 	DAYSPERNYEAR, DAYSPERLYEAR
196 };
197 
198 
199 /*
200  * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
201  * localtime.c 7.78.
202  * tzfile.h 1.8
203  * adapted to be replacement gmtime_r.
204  */
205 static void
c_timesub(timep,offset,tmp)206 c_timesub(timep, offset, tmp)
207 const time_64t * const			timep;
208 const long				offset;
209 struct tm * const		tmp;
210 {
211 	INT64			days;
212 	INT64			rem;
213 	INT64			y;
214 	int			yleap;
215 	const int *		ip;
216 
217 	days = *timep / SECSPERDAY;
218 	rem = *timep % SECSPERDAY;
219 	rem += (offset);
220 	while (rem < 0) {
221 		rem += SECSPERDAY;
222 		--days;
223 	}
224 	while (rem >= SECSPERDAY) {
225 		rem -= SECSPERDAY;
226 		++days;
227 	}
228 	tmp->tm_hour = (int) (rem / SECSPERHOUR);
229 	rem = rem % SECSPERHOUR;
230 	tmp->tm_min = (int) (rem / SECSPERMIN);
231 	/*
232 	** A positive leap second requires a special
233 	** representation.  This uses "... ??:59:60" et seq.
234 	*/
235 	tmp->tm_sec = (int) (rem % SECSPERMIN) ;
236 	tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
237 	if (tmp->tm_wday < 0)
238 		tmp->tm_wday += DAYSPERWEEK;
239 	y = EPOCH_YEAR;
240 #define LEAPS_THRU_END_OF(y)	((y) / 4 - (y) / 100 + (y) / 400)
241 	while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
242 		INT64	newy;
243 
244 		newy = y + days / DAYSPERNYEAR;
245 		if (days < 0)
246 			--newy;
247 		days -= (newy - y) * DAYSPERNYEAR +
248 			LEAPS_THRU_END_OF(newy - 1) -
249 			LEAPS_THRU_END_OF(y - 1);
250 		y = newy;
251 	}
252 	tmp->tm_year = (int)(y - TM_YEAR_BASE);
253 	tmp->tm_yday = (int) days;
254 	ip = mon_lengths[yleap];
255 	for (tmp->tm_mon = 0; days >= (INT64) ip[tmp->tm_mon]; ++(tmp->tm_mon))
256 		days = days - (INT64) ip[tmp->tm_mon];
257 	tmp->tm_mday = (int) (days + 1);
258 	tmp->tm_isdst = 0;
259 }
260 
261 /*
262 * Re-entrant version of gmtime.
263 */
c_gmtime_r(const time_64t * timep,struct tm * tm)264 struct tm * c_gmtime_r(const time_64t* timep, struct tm *tm)
265 {
266 	c_timesub(timep, 0L, tm);
267 	return tm;
268 }
269 
270 // Get the real-time system timer
TickRealtime()271 UINT TickRealtime()
272 {
273 #if	defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES) || defined(UNIX_MACOS)
274 	return Tick() + 1;
275 #else
276 	return TickRealtimeManual() + 1;
277 #endif
278 }
279 
280 #ifndef	OS_WIN32
281 
282 static UINT64 last_manual_tick = 0;
283 static UINT64 manual_tick_add_value = 0;
284 
285 // For systems which not have clock_gettime (such as MacOS X)
TickRealtimeManual()286 UINT TickRealtimeManual()
287 {
288 	UINT64 ret;
289 	Lock(tick_manual_lock);
290 	{
291 		ret = TickGetRealtimeTickValue64();
292 
293 		if (last_manual_tick != 0 && (last_manual_tick > ret))
294 		{
295 			manual_tick_add_value += (last_manual_tick - ret);
296 		}
297 
298 		last_manual_tick = ret;
299 	}
300 	Unlock(tick_manual_lock);
301 
302 	return (UINT)(ret + manual_tick_add_value);
303 }
304 
305 // Returns a appropriate value from the current time
TickGetRealtimeTickValue64()306 UINT64 TickGetRealtimeTickValue64()
307 {
308 	struct timeval tv;
309 	struct timezone tz;
310 	UINT64 ret;
311 
312 	memset(&tv, 0, sizeof(tv));
313 	memset(&tz, 0, sizeof(tz));
314 
315 	gettimeofday(&tv, &tz);
316 
317 	if (sizeof(tv.tv_sec) != 4)
318 	{
319 		ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
320 	}
321 	else
322 	{
323 		ret = (UINT64)((UINT64)((UINT32)tv.tv_sec)) * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
324 	}
325 
326 	return ret;
327 }
328 
329 #endif	// OS_WIN32
330 
331 // Get the number of CPUs
GetNumberOfCpu()332 UINT GetNumberOfCpu()
333 {
334 	UINT ret = 0;
335 
336 	if (cached_number_of_cpus == 0)
337 	{
338 		UINT i = 0;
339 
340 #ifdef	OS_WIN32
341 		i = Win32GetNumberOfCpuInner();
342 #else	// OS_WIN32
343 		i = UnixGetNumberOfCpuInner();
344 #endif	// OS_WIN32
345 
346 		if (i == 0)
347 		{
348 			i = 8;
349 		}
350 
351 		cached_number_of_cpus = i;
352 	}
353 
354 	ret = cached_number_of_cpus;
355 
356 	if (ret == 0)
357 	{
358 		ret = 1;
359 	}
360 	if (ret > 128)
361 	{
362 		ret = 128;
363 	}
364 
365 	return ret;
366 }
367 
368 // Creating a thread list
NewThreadList()369 LIST *NewThreadList()
370 {
371 	LIST *o = NewList(NULL);
372 
373 	return o;
374 }
375 
376 // Remove the thread from the thread list
DelThreadFromThreadList(LIST * o,THREAD * t)377 void DelThreadFromThreadList(LIST *o, THREAD *t)
378 {
379 	// Validate arguments
380 	if (o == NULL || t == NULL)
381 	{
382 		return;
383 	}
384 
385 	LockList(o);
386 	{
387 		if (Delete(o, t))
388 		{
389 			ReleaseThread(t);
390 		}
391 	}
392 	UnlockList(o);
393 }
394 
395 // Add the thread to the thread list
AddThreadToThreadList(LIST * o,THREAD * t)396 void AddThreadToThreadList(LIST *o, THREAD *t)
397 {
398 	// Validate arguments
399 	if (o == NULL || t == NULL)
400 	{
401 		return;
402 	}
403 
404 	LockList(o);
405 	{
406 		if (IsInList(o, t) == false)
407 		{
408 			AddRef(t->ref);
409 
410 			Add(o, t);
411 		}
412 	}
413 	UnlockList(o);
414 }
415 
416 // Maintain thread list
MainteThreadList(LIST * o)417 void MainteThreadList(LIST *o)
418 {
419 	UINT i;
420 	LIST *delete_list = NULL;
421 	// Validate arguments
422 	if (o == NULL)
423 	{
424 		return;
425 	}
426 
427 	LockList(o);
428 	{
429 		for (i = 0;i < LIST_NUM(o);i++)
430 		{
431 			THREAD *t = LIST_DATA(o, i);
432 
433 			if (t->Stopped)
434 			{
435 				if (delete_list == NULL)
436 				{
437 					delete_list = NewListFast(NULL);
438 				}
439 
440 				Add(delete_list, t);
441 			}
442 		}
443 
444 		if (delete_list != NULL)
445 		{
446 			for (i = 0;i < LIST_NUM(delete_list);i++)
447 			{
448 				THREAD *t = LIST_DATA(delete_list, i);
449 
450 				ReleaseThread(t);
451 
452 				Delete(o, t);
453 			}
454 
455 			ReleaseList(delete_list);
456 		}
457 	}
458 	UnlockList(o);
459 }
460 
461 // Wait until all threads in the thread list will be stopped
WaitAllThreadsWillBeStopped(LIST * o)462 void WaitAllThreadsWillBeStopped(LIST *o)
463 {
464 	// Validate arguments
465 	if (o == NULL)
466 	{
467 		return;
468 	}
469 
470 	while (LIST_NUM(o) != 0)
471 	{
472 		SleepThread(100);
473 	}
474 }
475 
476 // Stop all the threads in the thread list
StopThreadList(LIST * o)477 void StopThreadList(LIST *o)
478 {
479 	UINT i;
480 	// Validate arguments
481 	if (o == NULL)
482 	{
483 		return;
484 	}
485 
486 	LockList(o);
487 	{
488 		for (i = 0;i < LIST_NUM(o);i++)
489 		{
490 			THREAD *t = LIST_DATA(o, i);
491 
492 			WaitThread(t, INFINITE);
493 		}
494 	}
495 	UnlockList(o);
496 }
497 
498 // Release the thread list
FreeThreadList(LIST * o)499 void FreeThreadList(LIST *o)
500 {
501 	UINT i;
502 	// Validate arguments
503 	if (o == NULL)
504 	{
505 		return;
506 	}
507 
508 	LockList(o);
509 	{
510 		for (i = 0;i < LIST_NUM(o);i++)
511 		{
512 			THREAD *t = LIST_DATA(o, i);
513 
514 			WaitThread(t, INFINITE);
515 
516 			ReleaseThread(t);
517 		}
518 
519 		DeleteAll(o);
520 	}
521 	UnlockList(o);
522 
523 	ReleaseList(o);
524 }
525 
526 // Get the home directory
GetHomeDirW(wchar_t * path,UINT size)527 void GetHomeDirW(wchar_t *path, UINT size)
528 {
529 	// Validate arguments
530 	if (path == NULL)
531 	{
532 		return;
533 	}
534 
535 	if (GetEnvW(L"HOME", path, size) == false)
536 	{
537 		wchar_t drive[MAX_SIZE];
538 		wchar_t hpath[MAX_SIZE];
539 		if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
540 			GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
541 		{
542 			UniFormat(path, size, L"%s%s", drive, hpath);
543 		}
544 		else
545 		{
546 #ifdef	OS_WIN32
547 			Win32GetCurrentDirW(path, size);
548 #else	// OS_WIN32
549 			UnixGetCurrentDirW(path, size);
550 #endif	// OS_WIN32
551 		}
552 	}
553 }
GetHomeDir(char * path,UINT size)554 void GetHomeDir(char *path, UINT size)
555 {
556 	// Validate arguments
557 	if (path == NULL)
558 	{
559 		return;
560 	}
561 
562 	if (GetEnv("HOME", path, size) == false)
563 	{
564 		char drive[MAX_SIZE];
565 		char hpath[MAX_SIZE];
566 		if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
567 			GetEnv("HOMEPATH", hpath, sizeof(hpath)))
568 		{
569 			Format(path, size, "%s%s", drive, hpath);
570 		}
571 		else
572 		{
573 #ifdef	OS_WIN32
574 			Win32GetCurrentDir(path, size);
575 #else	// OS_WIN32
576 			UnixGetCurrentDir(path, size);
577 #endif	// OS_WIN32
578 		}
579 	}
580 }
581 
582 // Get the environment variable string
GetEnv(char * name,char * data,UINT size)583 bool GetEnv(char *name, char *data, UINT size)
584 {
585 	char *ret;
586 	// Validate arguments
587 	if (name == NULL || data == NULL)
588 	{
589 		return false;
590 	}
591 
592 	StrCpy(data, size, "");
593 
594 	ret = getenv(name);
595 	if (ret == NULL)
596 	{
597 		return false;
598 	}
599 
600 	StrCpy(data, size, ret);
601 
602 	return true;
603 }
GetEnvW(wchar_t * name,wchar_t * data,UINT size)604 bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
605 {
606 #ifdef	OS_WIN32
607 	return GetEnvW_ForWin32(name, data, size);
608 #else	// OS_WIN32
609 	return GetEnvW_ForUnix(name, data, size);
610 #endif	// OS_WIN32
611 }
612 
613 #ifdef	OS_WIN32
GetEnvW_ForWin32(wchar_t * name,wchar_t * data,UINT size)614 bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
615 {
616 	wchar_t *ret;
617 	// Validate arguments
618 	if (name == NULL || data == NULL)
619 	{
620 		return false;
621 	}
622 
623 	if (IsNt() == false)
624 	{
625 		bool ret;
626 		char *name_a = CopyUniToStr(name);
627 		char data_a[MAX_SIZE];
628 
629 		ret = GetEnv(name_a, data_a, sizeof(data_a));
630 
631 		if (ret)
632 		{
633 			StrToUni(data, size, data_a);
634 		}
635 
636 		Free(name_a);
637 
638 		return ret;
639 	}
640 
641 	UniStrCpy(data, size, L"");
642 
643 	ret = _wgetenv(name);
644 	if (ret == NULL)
645 	{
646 		return false;
647 	}
648 
649 	UniStrCpy(data, size, ret);
650 
651 	return true;
652 }
653 
654 #endif	// OS_WIN32
655 
656 #ifdef	OS_UNIX
657 
GetEnvW_ForUnix(wchar_t * name,wchar_t * data,UINT size)658 bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
659 {
660 	char *name_a;
661 	bool ret;
662 	char data_a[MAX_SIZE];
663 	// Validate arguments
664 	if (name == NULL || data == NULL)
665 	{
666 		return false;
667 	}
668 
669 	name_a = CopyUniToUtf(name);
670 
671 	ret = GetEnv(name_a, data_a, sizeof(data_a));
672 
673 	if (ret)
674 	{
675 		UtfToUni(data, size, data_a);
676 	}
677 
678 	Free(name_a);
679 
680 	return ret;
681 }
682 
683 #endif	// OS_UNIX
684 
685 // Get the memory information
GetMemInfo(MEMINFO * info)686 void GetMemInfo(MEMINFO *info)
687 {
688 	OSGetMemInfo(info);
689 }
690 
691 // Start the single-instance
NewSingleInstance(char * instance_name)692 INSTANCE *NewSingleInstance(char *instance_name)
693 {
694 	return NewSingleInstanceEx(instance_name, false);
695 }
NewSingleInstanceEx(char * instance_name,bool user_local)696 INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
697 {
698 	char name[MAX_SIZE];
699 	INSTANCE *ret;
700 	void *data;
701 
702 	if (instance_name != NULL)
703 	{
704 		if (user_local == false)
705 		{
706 			HashInstanceName(name, sizeof(name), instance_name);
707 		}
708 		else
709 		{
710 			HashInstanceNameLocal(name, sizeof(name), instance_name);
711 		}
712 
713 		data = OSNewSingleInstance(name);
714 	}
715 	else
716 	{
717 		data = OSNewSingleInstance(NULL);
718 	}
719 
720 	if (data == NULL)
721 	{
722 		return NULL;
723 	}
724 
725 	ret = ZeroMalloc(sizeof(INSTANCE));
726 	if (instance_name != NULL)
727 	{
728 		ret->Name = CopyStr(instance_name);
729 	}
730 
731 	ret->pData = data;
732 
733 	return ret;
734 }
735 
736 // Release of single instance
FreeSingleInstance(INSTANCE * inst)737 void FreeSingleInstance(INSTANCE *inst)
738 {
739 	// Validate arguments
740 	if (inst == NULL)
741 	{
742 		return;
743 	}
744 
745 	OSFreeSingleInstance(inst->pData);
746 
747 	if (inst->Name != NULL)
748 	{
749 		Free(inst->Name);
750 	}
751 	Free(inst);
752 }
753 
754 // Hashing the instance name
HashInstanceName(char * name,UINT size,char * instance_name)755 void HashInstanceName(char *name, UINT size, char *instance_name)
756 {
757 	char tmp[MAX_SIZE];
758 	UCHAR hash[SHA1_SIZE];
759 	char key[11];
760 	// Validate arguments
761 	if (name == NULL || instance_name == NULL)
762 	{
763 		return;
764 	}
765 
766 	StrCpy(tmp, sizeof(tmp), instance_name);
767 	Trim(tmp);
768 	StrUpper(tmp);
769 
770 	Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
771 	BinToStr(key, sizeof(key), hash, 5);
772 	key[10] = 0;
773 
774 	Format(name, size, "VPN-%s", key);
775 
776 	if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
777 	{
778 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
779 			GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
780 		{
781 			StrCpy(tmp, sizeof(tmp), name);
782 			Format(name, size, "Global\\%s", tmp);
783 		}
784 	}
785 }
HashInstanceNameLocal(char * name,UINT size,char * instance_name)786 void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
787 {
788 	char tmp[MAX_SIZE];
789 	UCHAR hash[SHA1_SIZE];
790 	char key[11];
791 	// Validate arguments
792 	if (name == NULL || instance_name == NULL)
793 	{
794 		return;
795 	}
796 
797 	StrCpy(tmp, sizeof(tmp), instance_name);
798 	Trim(tmp);
799 	StrUpper(tmp);
800 
801 	Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
802 	BinToStr(key, sizeof(key), hash, 5);
803 	key[10] = 0;
804 
805 	Format(name, size, "VPN-%s", key);
806 
807 	if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
808 	{
809 		if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
810 			GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
811 		{
812 			StrCpy(tmp, sizeof(tmp), name);
813 			Format(name, size, "Local\\%s", tmp);
814 		}
815 	}
816 }
817 
818 // Run the process
Run(char * filename,char * arg,bool hide,bool wait)819 bool Run(char *filename, char *arg, bool hide, bool wait)
820 {
821 	// Validate arguments
822 	if (filename == NULL)
823 	{
824 		return false;
825 	}
826 
827 	return OSRun(filename, arg, hide, wait);
828 }
RunW(wchar_t * filename,wchar_t * arg,bool hide,bool wait)829 bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
830 {
831 	// Validate arguments
832 	if (filename == NULL)
833 	{
834 		return false;
835 	}
836 
837 	return OSRunW(filename, arg, hide, wait);
838 }
839 
840 // Date and time related functions
GetDateTimeStr64Uni(wchar_t * str,UINT size,UINT64 sec64)841 void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
842 {
843 	char tmp[MAX_SIZE];
844 	if (str == NULL)
845 	{
846 		return;
847 	}
848 
849 	GetDateTimeStr64(tmp, sizeof(tmp), sec64);
850 	StrToUni(str, size, tmp);
851 }
GetDateTimeStr64(char * str,UINT size,UINT64 sec64)852 void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
853 {
854 	SYSTEMTIME st;
855 	UINT64ToSystem(&st, sec64);
856 	GetDateTimeStr(str, size, &st);
857 }
GetDateTimeStrMilli64(char * str,UINT size,UINT64 sec64)858 void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
859 {
860 	SYSTEMTIME st;
861 	UINT64ToSystem(&st, sec64);
862 	GetDateTimeStrMilli(str, size, &st);
863 }
GetDateTimeStrMilli64ForFileName(char * str,UINT size,UINT64 sec64)864 void GetDateTimeStrMilli64ForFileName(char *str, UINT size, UINT64 sec64)
865 {
866 	SYSTEMTIME st;
867 	UINT64ToSystem(&st, sec64);
868 	GetDateTimeStrMilliForFileName(str, size, &st);
869 }
GetDateTimeStrMilliForFileName(char * str,UINT size,SYSTEMTIME * tm)870 void GetDateTimeStrMilliForFileName(char *str, UINT size, SYSTEMTIME *tm)
871 {
872 	Format(str, size, "%04u%02u%02u_%02u%02u%02u",
873 		tm->wYear, tm->wMonth, tm->wDay, tm->wHour, tm->wMinute, tm->wSecond);
874 }
GetDateStr64(char * str,UINT size,UINT64 sec64)875 void GetDateStr64(char *str, UINT size, UINT64 sec64)
876 {
877 	SYSTEMTIME st;
878 	if (sec64 == 0)
879 	{
880 		StrCpy(str, size, "(Unknown)");
881 		return;
882 	}
883 	UINT64ToSystem(&st, sec64);
884 	GetDateStr(str, size, &st);
885 }
GetDateTimeStrEx64(wchar_t * str,UINT size,UINT64 sec64,LOCALE * locale)886 void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
887 {
888 	SYSTEMTIME st;
889 	if (locale == NULL)
890 	{
891 		locale = &current_locale;
892 	}
893 	if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
894 	{
895 		UniStrCpy(str, size, locale->Unknown);
896 		return;
897 	}
898 	UINT64ToSystem(&st, sec64);
899 	GetDateTimeStrEx(str, size, &st, locale);
900 }
GetTimeStrEx64(wchar_t * str,UINT size,UINT64 sec64,LOCALE * locale)901 void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
902 {
903 	SYSTEMTIME st;
904 	if (locale == NULL)
905 	{
906 		locale = &current_locale;
907 	}
908 	if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
909 	{
910 		UniStrCpy(str, size, locale->Unknown);
911 		return;
912 	}
913 	UINT64ToSystem(&st, sec64);
914 	GetTimeStrEx(str, size, &st, locale);
915 }
GetDateStrEx64(wchar_t * str,UINT size,UINT64 sec64,LOCALE * locale)916 void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
917 {
918 	SYSTEMTIME st;
919 	if (locale == NULL)
920 	{
921 		locale = &current_locale;
922 	}
923 	if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
924 	{
925 		UniStrCpy(str, size, locale->Unknown);
926 		return;
927 	}
928 	UINT64ToSystem(&st, sec64);
929 	GetDateStrEx(str, size, &st, locale);
930 }
GetTimeStrMilli64(char * str,UINT size,UINT64 sec64)931 void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
932 {
933 	SYSTEMTIME st;
934 	if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
935 	{
936 		StrCpy(str, size, "(Unknown)");
937 		return;
938 	}
939 	UINT64ToSystem(&st, sec64);
940 	GetTimeStrMilli(str, size, &st);
941 }
GetTimeStr64(char * str,UINT size,UINT64 sec64)942 void GetTimeStr64(char *str, UINT size, UINT64 sec64)
943 {
944 	SYSTEMTIME st;
945 	if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
946 	{
947 		StrCpy(str, size, "(Unknown)");
948 		return;
949 	}
950 	UINT64ToSystem(&st, sec64);
951 	GetTimeStr(str, size, &st);
952 }
953 
954 // Convert to a time to be used safely in the current POSIX implementation
SafeTime64(UINT64 sec64)955 UINT64 SafeTime64(UINT64 sec64)
956 {
957 	return MAKESURE(sec64, 0, 4102243323123ULL);
958 }
959 
960 // Thread pool
961 static SK *thread_pool = NULL;
962 static COUNTER *thread_count = NULL;
963 
964 // Initialization of thread pool
InitThreading()965 void InitThreading()
966 {
967 	thread_pool = NewSk();
968 	thread_count = NewCounter();
969 }
970 
971 // Release of thread pool
FreeThreading()972 void FreeThreading()
973 {
974 	while (true)
975 	{
976 		if (Count(thread_count) == 0)
977 		{
978 			break;
979 		}
980 
981 		SleepThread(25);
982 	}
983 
984 	while (true)
985 	{
986 		THREAD_POOL_DATA *pd;
987 		THREAD *t = Pop(thread_pool);
988 
989 		if (t == NULL)
990 		{
991 			break;
992 		}
993 
994 		pd = (THREAD_POOL_DATA *)t->param;
995 
996 		pd->ThreadProc = NULL;
997 		Set(pd->Event);
998 
999 		WaitThreadInternal(t);
1000 
1001 		pd = (THREAD_POOL_DATA *)t->param;
1002 		ReleaseEvent(pd->Event);
1003 		ReleaseEvent(pd->InitFinishEvent);
1004 
1005 		ReleaseThreadInternal(t);
1006 
1007 		Free(pd);
1008 	}
1009 
1010 	ReleaseSk(thread_pool);
1011 
1012 	DeleteCounter(thread_count);
1013 	thread_count = NULL;
1014 }
1015 
1016 // Thread pool procedure
ThreadPoolProc(THREAD * t,void * param)1017 void ThreadPoolProc(THREAD *t, void *param)
1018 {
1019 	THREAD_POOL_DATA *pd;
1020 	// Validate arguments
1021 	if (t == NULL)
1022 	{
1023 		return;
1024 	}
1025 
1026 	pd = (THREAD_POOL_DATA *)param;
1027 
1028 	NoticeThreadInitInternal(t);
1029 
1030 	while (true)
1031 	{
1032 		THREAD *thread;
1033 		UINT i, num;
1034 		EVENT **ee;
1035 
1036 		// Wait for the next job
1037 		Wait(pd->Event, INFINITE);
1038 
1039 		if (pd->ThreadProc == NULL)
1040 		{
1041 			// Stop the pool thread
1042 			break;
1043 		}
1044 
1045 		thread = pd->Thread;
1046 		thread->ThreadId = ThreadId();
1047 
1048 		// Initialization is completed
1049 		Set(pd->InitFinishEvent);
1050 
1051 		// Set the thread name
1052 		if (thread->Name != NULL)
1053 		{
1054 			SetThreadName(thread->ThreadId, thread->Name, thread->param);
1055 		}
1056 		else
1057 		{
1058 			SetThreadName(thread->ThreadId, "Unknown", 0);
1059 		}
1060 
1061 		// Run the thread procedure
1062 		pd->ThreadProc(pd->Thread, thread->param);
1063 
1064 		// Set the thread name
1065 		SetThreadName(thread->ThreadId, NULL, 0);
1066 
1067 		pd->Thread->Stopped = true;
1068 
1069 		thread->PoolHalting = true;
1070 
1071 		// Set the waiting event list
1072 		LockList(thread->PoolWaitList);
1073 		{
1074 			num = LIST_NUM(thread->PoolWaitList);
1075 			ee = ToArray(thread->PoolWaitList);
1076 
1077 			DeleteAll(thread->PoolWaitList);
1078 		}
1079 		UnlockList(thread->PoolWaitList);
1080 
1081 		for (i = 0;i < num;i++)
1082 		{
1083 			EVENT *e = ee[i];
1084 
1085 			Set(e);
1086 			ReleaseEvent(e);
1087 		}
1088 
1089 		Free(ee);
1090 
1091 		while (true)
1092 		{
1093 			if (Count(thread->ref->c) <= 1)
1094 			{
1095 				break;
1096 			}
1097 
1098 			Wait(thread->release_event, 256);
1099 		}
1100 
1101 		ReleaseThread(thread);
1102 
1103 #ifdef	OS_WIN32
1104 		// For Win32: Recover the priority of the thread
1105 		MsRestoreThreadPriority();
1106 #endif	// OS_WIN32
1107 
1108 		// Register the thread itself to the thread pool
1109 		LockSk(thread_pool);
1110 		{
1111 			Push(thread_pool, t);
1112 		}
1113 		UnlockSk(thread_pool);
1114 
1115 		Dec(thread_count);
1116 	}
1117 }
1118 
1119 // Set the thread name
SetThreadName(uintmax_t thread_id,char * name,void * param)1120 void SetThreadName(uintmax_t thread_id, char *name, void *param)
1121 {
1122 #ifdef	OS_WIN32
1123 	if (IsDebug())
1124 	{
1125 		char tmp[MAX_SIZE];
1126 
1127 		if (name == NULL)
1128 		{
1129 			strcpy(tmp, "idle");
1130 		}
1131 		else
1132 		{
1133 			sprintf(tmp, "%s (0x%x)", name, (UINT)param);
1134 		}
1135 
1136 		Win32SetThreadName(thread_id, tmp);
1137 	}
1138 #else	// OS_WIN32
1139 #ifdef	_DEBUG
1140 #ifdef	PR_SET_NAME
1141 	char tmp[MAX_SIZE];
1142 
1143 	if (name == NULL)
1144 	{
1145 		strcpy(tmp, "idle");
1146 	}
1147 	else
1148 	{
1149 		sprintf(tmp, "%s (%p)", name, param);
1150 	}
1151 
1152 	tmp[15] = 0;
1153 
1154 	prctl(PR_SET_NAME, (unsigned long)tmp, 0, 0, 0);
1155 #endif	// PR_SET_NAME
1156 #endif	// _DEBUG
1157 #endif	// OS_WIN32
1158 }
1159 
1160 // Do Nothing
DoNothing()1161 UINT DoNothing()
1162 {
1163 	return g_zero;
1164 }
1165 
1166 // Thread creation (pool)
NewThreadNamed(THREAD_PROC * thread_proc,void * param,char * name)1167 THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
1168 {
1169 	THREAD *host = NULL;
1170 	THREAD_POOL_DATA *pd = NULL;
1171 	THREAD *ret;
1172 	bool new_thread = false;
1173 	// Validate arguments
1174 	if (thread_proc == NULL)
1175 	{
1176 		return NULL;
1177 	}
1178 
1179 	if (IsTrackingEnabled() == false)
1180 	{
1181 		DoNothing();
1182 	}
1183 
1184 	Inc(thread_count);
1185 
1186 	LockSk(thread_pool);
1187 	{
1188 		// Examine whether there is a thread that is currently vacant in the pool
1189 		host = Pop(thread_pool);
1190 	}
1191 	UnlockSk(thread_pool);
1192 
1193 	if (host == NULL)
1194 	{
1195 		// Create a new thread because a vacant thread is not found
1196 		pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
1197 		pd->Event = NewEvent();
1198 		pd->InitFinishEvent = NewEvent();
1199 		host = NewThreadInternal(ThreadPoolProc, pd);
1200 		WaitThreadInitInternal(host);
1201 
1202 		new_thread = true;
1203 	}
1204 	else
1205 	{
1206 		pd = (THREAD_POOL_DATA *)host->param;
1207 	}
1208 
1209 	// Creating a thread pool
1210 	ret = ZeroMalloc(sizeof(THREAD));
1211 	ret->ref = NewRef();
1212 	ret->thread_proc = thread_proc;
1213 	ret->param = param;
1214 	ret->pData = NULL;
1215 	ret->init_finished_event = NewEvent();
1216 	ret->PoolThread = true;
1217 	ret->PoolWaitList = NewList(NULL);
1218 	ret->PoolHostThread = host;
1219 	ret->release_event = NewEvent();
1220 
1221 	if (IsEmptyStr(name) == false)
1222 	{
1223 		ret->Name = CopyStr(name);
1224 	}
1225 
1226 	// Run
1227 	pd->ThreadProc = thread_proc;
1228 	pd->Thread = ret;
1229 	AddRef(ret->ref);
1230 
1231 	Set(pd->Event);
1232 
1233 	Wait(pd->InitFinishEvent, INFINITE);
1234 
1235 	current_num_thread++;
1236 
1237 //	Debug("current_num_thread = %u\n", current_num_thread);
1238 
1239 	return ret;
1240 }
1241 
1242 // Clean up of thread (pool)
CleanupThread(THREAD * t)1243 void CleanupThread(THREAD *t)
1244 {
1245 	// Validate arguments
1246 	if (t == NULL)
1247 	{
1248 		return;
1249 	}
1250 
1251 	ReleaseEvent(t->init_finished_event);
1252 	ReleaseEvent(t->release_event);
1253 	ReleaseList(t->PoolWaitList);
1254 
1255 	if (t->Name != NULL)
1256 	{
1257 		Free(t->Name);
1258 	}
1259 
1260 	Free(t);
1261 
1262 	current_num_thread--;
1263 	//Debug("current_num_thread = %u\n", current_num_thread);
1264 }
1265 
1266 // Release thread (pool)
ReleaseThread(THREAD * t)1267 void ReleaseThread(THREAD *t)
1268 {
1269 	UINT ret;
1270 	EVENT *e;
1271 	// Validate arguments
1272 	if (t == NULL)
1273 	{
1274 		return;
1275 	}
1276 
1277 	e = t->release_event;
1278 	if (e != NULL)
1279 	{
1280 		AddRef(e->ref);
1281 	}
1282 
1283 	ret = Release(t->ref);
1284 	Set(e);
1285 
1286 	ReleaseEvent(e);
1287 
1288 	if (ret == 0)
1289 	{
1290 		CleanupThread(t);
1291 	}
1292 }
1293 
1294 // Notify the completion of the thread initialization (pool)
NoticeThreadInit(THREAD * t)1295 void NoticeThreadInit(THREAD *t)
1296 {
1297 	// Validate arguments
1298 	if (t == NULL)
1299 	{
1300 		return;
1301 	}
1302 
1303 	// Notification
1304 	Set(t->init_finished_event);
1305 }
1306 
1307 // Wait the completion of the thread initialization (pool)
WaitThreadInit(THREAD * t)1308 void WaitThreadInit(THREAD *t)
1309 {
1310 	// Validate arguments
1311 	if (t == NULL)
1312 	{
1313 		return;
1314 	}
1315 
1316 	// KS
1317 	KS_INC(KS_WAITFORTHREAD_COUNT);
1318 
1319 	// Wait
1320 	Wait(t->init_finished_event, INFINITE);
1321 }
1322 
1323 // Wait for the termination of the thread (pool)
WaitThread(THREAD * t,UINT timeout)1324 bool WaitThread(THREAD *t, UINT timeout)
1325 {
1326 	bool ret = false;
1327 	EVENT *e = NULL;
1328 	// Validate arguments
1329 	if (t == NULL)
1330 	{
1331 		return false;
1332 	}
1333 
1334 	LockList(t->PoolWaitList);
1335 	{
1336 		if (t->PoolHalting)
1337 		{
1338 			// Has already been stopped
1339 			ret = true;
1340 		}
1341 		else
1342 		{
1343 			// Register the completion notifying event to the list
1344 			e = NewEvent();
1345 			AddRef(e->ref);
1346 			Insert(t->PoolWaitList, e);
1347 		}
1348 	}
1349 	UnlockList(t->PoolWaitList);
1350 
1351 	if (e != NULL)
1352 	{
1353 		// Wait Event
1354 		ret = Wait(e, timeout);
1355 
1356 		LockList(t->PoolWaitList);
1357 		{
1358 			if (Delete(t->PoolWaitList, e))
1359 			{
1360 				ReleaseEvent(e);
1361 			}
1362 		}
1363 		UnlockList(t->PoolWaitList);
1364 
1365 		ReleaseEvent(e);
1366 	}
1367 
1368 	return ret;
1369 }
1370 
1371 // Get Thread ID
ThreadId()1372 UINT ThreadId()
1373 {
1374 	return OSThreadId();
1375 }
1376 
1377 // Creating a thread
NewThreadInternal(THREAD_PROC * thread_proc,void * param)1378 THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
1379 {
1380 	THREAD *t;
1381 	UINT retry = 0;
1382 	// Validate arguments
1383 	if (thread_proc == NULL)
1384 	{
1385 		return NULL;
1386 	}
1387 
1388 	// Initialize Thread object
1389 	t = ZeroMalloc(sizeof(THREAD));
1390 	t->init_finished_event = NewEvent();
1391 
1392 	t->param = param;
1393 	t->ref = NewRef();
1394 	t->thread_proc = thread_proc;
1395 
1396 	// Wait until the OS to initialize the thread
1397 	while (true)
1398 	{
1399 		if ((retry++) > 60)
1400 		{
1401 			printf("\n\n*** error: new thread create failed.\n\n");
1402 			AbortExit();
1403 		}
1404 		if (OSInitThread(t))
1405 		{
1406 			break;
1407 		}
1408 		SleepThread(500);
1409 	}
1410 
1411 	// KS
1412 	KS_INC(KS_NEWTHREAD_COUNT);
1413 
1414 	return t;
1415 }
1416 
1417 // Release of thread
ReleaseThreadInternal(THREAD * t)1418 void ReleaseThreadInternal(THREAD *t)
1419 {
1420 	// Validate arguments
1421 	if (t == NULL)
1422 	{
1423 		return;
1424 	}
1425 
1426 	if (Release(t->ref) == 0)
1427 	{
1428 		CleanupThreadInternal(t);
1429 	}
1430 }
1431 
1432 // Clean up of the thread
CleanupThreadInternal(THREAD * t)1433 void CleanupThreadInternal(THREAD *t)
1434 {
1435 	// Validate arguments
1436 	if (t == NULL)
1437 	{
1438 		return;
1439 	}
1440 
1441 	// Release of the thread
1442 	OSFreeThread(t);
1443 
1444 	// Release the event
1445 	ReleaseEvent(t->init_finished_event);
1446 	// Memory release
1447 	Free(t);
1448 
1449 	// KS
1450 	KS_INC(KS_FREETHREAD_COUNT);
1451 }
1452 
1453 // Wait for the termination of the thread
WaitThreadInternal(THREAD * t)1454 bool WaitThreadInternal(THREAD *t)
1455 {
1456 	// Validate arguments
1457 	if (t == NULL)
1458 	{
1459 		return false;
1460 	}
1461 
1462 	return OSWaitThread(t);
1463 }
1464 
1465 // Notify that the thread initialization is complete
NoticeThreadInitInternal(THREAD * t)1466 void NoticeThreadInitInternal(THREAD *t)
1467 {
1468 	// Validate arguments
1469 	if (t == NULL)
1470 	{
1471 		return;
1472 	}
1473 
1474 	// Notify
1475 	Set(t->init_finished_event);
1476 }
1477 
1478 // Wait for completion of thread initialization
WaitThreadInitInternal(THREAD * t)1479 void WaitThreadInitInternal(THREAD *t)
1480 {
1481 	// Validate arguments
1482 	if (t == NULL)
1483 	{
1484 		return;
1485 	}
1486 
1487 	// KS
1488 	KS_INC(KS_WAITFORTHREAD_COUNT);
1489 
1490 	// Wait
1491 	Wait(t->init_finished_event, INFINITE);
1492 }
1493 
1494 // Get the date and time string by using the locale information
GetDateTimeStrEx(wchar_t * str,UINT size,SYSTEMTIME * st,LOCALE * locale)1495 void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1496 {
1497 	wchar_t tmp1[MAX_SIZE];
1498 	wchar_t tmp2[MAX_SIZE];
1499 	// Validate arguments
1500 	if (str == NULL || st == NULL)
1501 	{
1502 		return;
1503 	}
1504 
1505 	GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
1506 	GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
1507 	UniFormat(str, size, L"%s %s", tmp1, tmp2);
1508 }
1509 
1510 // Get the time string by using the locale information
GetTimeStrEx(wchar_t * str,UINT size,SYSTEMTIME * st,LOCALE * locale)1511 void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1512 {
1513 	wchar_t *tag = L"%02u%s%02u%s%02u%s";
1514 	// Validate arguments
1515 	if (str == NULL || st == NULL)
1516 	{
1517 		return;
1518 	}
1519 
1520 	if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
1521 	{
1522 		tag = L"%2u%s%2u%s%2u%s";
1523 	}
1524 
1525 	locale = (locale != NULL ? locale : &current_locale);
1526 	UniFormat(str, size,
1527 		tag,
1528 		st->wHour, locale->HourStr,
1529 		st->wMinute, locale->MinuteStr,
1530 		st->wSecond, locale->SecondStr);
1531 }
1532 
1533 // Get a date string by using the locale information
GetDateStrEx(wchar_t * str,UINT size,SYSTEMTIME * st,LOCALE * locale)1534 void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
1535 {
1536 	wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
1537 	// Validate arguments
1538 	if (str == NULL || st == NULL)
1539 	{
1540 		return;
1541 	}
1542 
1543 	if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
1544 	{
1545 		tag = L"%4u%s%2u%s%2u%s(%s)";
1546 	}
1547 
1548 	locale = (locale != NULL ? locale : &current_locale);
1549 	UniFormat(str, size,
1550 		tag,
1551 		st->wYear, locale->YearStr,
1552 		st->wMonth, locale->MonthStr,
1553 		st->wDay, locale->DayStr,
1554 		locale->DayOfWeek[st->wDayOfWeek]);
1555 }
1556 
1557 // Get the time string to milliseconds (for example, 12:34:56.789)
GetTimeStrMilli(char * str,UINT size,SYSTEMTIME * st)1558 void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
1559 {
1560 	// Validate arguments
1561 	if (st == NULL || str == NULL)
1562 	{
1563 		return;
1564 	}
1565 
1566 	Format(str, size, "%02u:%02u:%02u.%03u",
1567 		st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
1568 }
1569 
1570 // Get the time string (for example, 12:34:56)
GetTimeStr(char * str,UINT size,SYSTEMTIME * st)1571 void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
1572 {
1573 	// Validate arguments
1574 	if (str == NULL || st == NULL)
1575 	{
1576 		return;
1577 	}
1578 
1579 	Format(str, size, "%02u:%02u:%02u",
1580 		st->wHour, st->wMinute, st->wSecond);
1581 }
1582 
1583 // Get the date string (example: 2004/07/23)
GetDateStr(char * str,UINT size,SYSTEMTIME * st)1584 void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
1585 {
1586 	// Validate arguments
1587 	if (str == NULL || st == NULL)
1588 	{
1589 		return;
1590 	}
1591 
1592 	Format(str, size, "%04u-%02u-%02u",
1593 		st->wYear, st->wMonth, st->wDay);
1594 }
1595 
1596 // Get the date and time string (example: 2004/07/23 12:34:56)
GetDateTimeStr(char * str,UINT size,SYSTEMTIME * st)1597 void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
1598 {
1599 	// Validate arguments
1600 	if (str == NULL || st == NULL)
1601 	{
1602 		return;
1603 	}
1604 
1605 	Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
1606 		st->wYear, st->wMonth, st->wDay,
1607 		st->wHour, st->wMinute, st->wSecond);
1608 }
1609 
1610 // Get the date and time string in milliseconds (example: 2004/07/23 12:34:56.789)
GetDateTimeStrMilli(char * str,UINT size,SYSTEMTIME * st)1611 void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
1612 {
1613 	// Validate arguments
1614 	if (str == NULL || st == NULL)
1615 	{
1616 		return;
1617 	}
1618 
1619 	Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
1620 		st->wYear, st->wMonth, st->wDay,
1621 		st->wHour, st->wMinute, st->wSecond,
1622 		st->wMilliseconds);
1623 }
1624 
1625 // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to UINT64
DateTimeStrRFC3339ToSystemTime64(char * str)1626 UINT64 DateTimeStrRFC3339ToSystemTime64(char *str)
1627 {
1628 	SYSTEMTIME st;
1629 	if (DateTimeStrRFC3339ToSystemTime(&st, str))
1630 	{
1631 		return SystemToUINT64(&st);
1632 	}
1633 	else
1634 	{
1635 		return 0;
1636 	}
1637 }
1638 
1639 // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to SYSTEMTIME
DateTimeStrRFC3339ToSystemTime(SYSTEMTIME * st,char * str)1640 bool DateTimeStrRFC3339ToSystemTime(SYSTEMTIME *st, char *str)
1641 {
1642 	bool ok = false;
1643 	UINT index_plus;
1644 	char tmp[MAX_PATH];
1645 	Zero(st, sizeof(SYSTEMTIME));
1646 	if (st == NULL || str == NULL)
1647 	{
1648 		return false;
1649 	}
1650 
1651 	StrCpy(tmp, sizeof(tmp), str);
1652 
1653 	index_plus = SearchStrEx(tmp, "+", 0, false);
1654 	if (index_plus != INFINITE)
1655 	{
1656 		tmp[index_plus] = 0;
1657 	}
1658 
1659 	if (StrLen(tmp) >= 19)
1660 	{
1661 		if (tmp[4] == '-' && tmp[7] == '-' && tmp[10] == 'T' && tmp[13] == ':' &&
1662 			tmp[16] == ':')
1663 		{
1664 			char str_year[16], str_month[16], str_day[16], str_hour[16], str_minute[16],
1665 				 str_second[16], str_msec[16];
1666 
1667 			StrCpy(str_year, sizeof(str_year), tmp + 0);
1668 			str_year[4] = 0;
1669 
1670 			StrCpy(str_month, sizeof(str_month), tmp + 5);
1671 			str_month[2] = 0;
1672 
1673 			StrCpy(str_day, sizeof(str_day), tmp + 8);
1674 			str_day[2] = 0;
1675 
1676 			StrCpy(str_hour, sizeof(str_hour), tmp + 11);
1677 			str_hour[2] = 0;
1678 
1679 			StrCpy(str_minute, sizeof(str_minute), tmp + 14);
1680 			str_minute[2] = 0;
1681 
1682 			StrCpy(str_second, sizeof(str_second), tmp + 17);
1683 			str_second[2] = 0;
1684 
1685 			str_msec[0] = 0;
1686 
1687 			if (StrLen(tmp) >= 21 && tmp[19] == '.')
1688 			{
1689 				StrCpy(str_msec, sizeof(str_msec), tmp + 20);
1690 				str_msec[StrLen(tmp) - 21] = 0;
1691 				while (StrLen(str_msec) < 3)
1692 				{
1693 					StrCat(str_msec, sizeof(str_msec), "0");
1694 				}
1695 				str_msec[3] = 0;
1696 			}
1697 
1698 			st->wYear = ToInt(str_year);
1699 			st->wMonth = ToInt(str_month);
1700 			st->wDay = ToInt(str_day);
1701 			st->wHour = ToInt(str_hour);
1702 			st->wMinute = ToInt(str_minute);
1703 			st->wSecond = ToInt(str_second);
1704 			st->wMilliseconds = ToInt(str_msec);
1705 
1706 			NormalizeSystem(st);
1707 
1708 			ok = true;
1709 		}
1710 	}
1711 
1712 	return ok;
1713 }
1714 
1715 // Get the date and time string in RFC3339 format (example: 2017-09-27T18:25:55.434-9:00)
GetDateTimeStrRFC3339(char * str,UINT size,SYSTEMTIME * st,int timezone_min)1716 void GetDateTimeStrRFC3339(char *str, UINT size, SYSTEMTIME *st, int timezone_min){
1717 	// Validate arguments
1718 	if (str == NULL || st == NULL)
1719 	{
1720 		ClearStr(str, size);
1721 		return;
1722 	}
1723 
1724 	if(timezone_min == 0){
1725 		Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ",
1726 		st->wYear, st->wMonth, st->wDay,
1727 		st->wHour, st->wMinute, st->wSecond,
1728 		st->wMilliseconds);
1729 	}else{
1730 		Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03u%+02d:%02d",
1731 		st->wYear, st->wMonth, st->wDay,
1732 		st->wHour, st->wMinute, st->wSecond,
1733 		st->wMilliseconds, timezone_min/60, timezone_min%60);
1734 	}
1735 }
1736 
1737 // Get the time string
GetSpanStr(char * str,UINT size,UINT64 sec64)1738 void GetSpanStr(char *str, UINT size, UINT64 sec64)
1739 {
1740 	char tmp[MAX_SIZE];
1741 	// Validate arguments
1742 	if (str == NULL)
1743 	{
1744 		return;
1745 	}
1746 
1747 	StrCpy(tmp, sizeof(tmp), "");
1748 	if (sec64 >= (UINT64)(1000 * 3600 * 24))
1749 	{
1750 		Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
1751 	}
1752 
1753 	Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
1754 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1755 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1756 		(UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
1757 
1758 	Trim(tmp);
1759 	StrCpy(str, size, tmp);
1760 }
1761 
1762 // Get the time string (in milliseconds)
GetSpanStrMilli(char * str,UINT size,UINT64 sec64)1763 void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
1764 {
1765 	char tmp[MAX_SIZE];
1766 	// Validate arguments
1767 	if (str == NULL)
1768 	{
1769 		return;
1770 	}
1771 
1772 	StrCpy(tmp, sizeof(tmp), "");
1773 	if (sec64 >= (UINT64)(1000 * 3600 * 24))
1774 	{
1775 		Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
1776 	}
1777 
1778 	Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
1779 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1780 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1781 		(UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
1782 		(UINT)(sec64 % (UINT64)(1000)));
1783 
1784 	Trim(tmp);
1785 	StrCpy(str, size, tmp);
1786 }
1787 
1788 // Get the time string (extended)
GetSpanStrEx(wchar_t * str,UINT size,UINT64 sec64,LOCALE * locale)1789 void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
1790 {
1791 	wchar_t tmp[MAX_SIZE];
1792 	// Validate arguments
1793 	if (str == NULL)
1794 	{
1795 		return;
1796 	}
1797 
1798 	locale = (locale != NULL ? locale : &current_locale);
1799 
1800 	UniStrCpy(tmp, sizeof(tmp), L"");
1801 	if (sec64 >= (UINT64)(1000 * 3600 * 24))
1802 	{
1803 		UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
1804 			locale->SpanDay);
1805 	}
1806 
1807 	UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
1808 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
1809 		locale->SpanHour,
1810 		(UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
1811 		locale->SpanMinute,
1812 		(UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
1813 		locale->SpanSecond);
1814 
1815 	UniTrim(tmp);
1816 	UniStrCpy(str, size, tmp);
1817 }
1818 
1819 // Get the current locale information
GetCurrentLocale(LOCALE * locale)1820 void GetCurrentLocale(LOCALE *locale)
1821 {
1822 	// Validate arguments
1823 	if (locale == NULL)
1824 	{
1825 		return;
1826 	}
1827 
1828 	Copy(locale, &current_locale, sizeof(LOCALE));
1829 }
1830 
1831 // Set the locale information
SetLocale(wchar_t * str)1832 void SetLocale(wchar_t *str)
1833 {
1834 	wchar_t *set_locale_str;
1835 	LOCALE tmp;
1836 
1837 	if (str != NULL)
1838 	{
1839 		set_locale_str = str;
1840 	}
1841 	else
1842 	{
1843 		set_locale_str = default_locale_str;
1844 	}
1845 
1846 	if (LoadLocale(&tmp, set_locale_str) == false)
1847 	{
1848 		if (LoadLocale(&tmp, default_locale_str) == false)
1849 		{
1850 			return;
1851 		}
1852 	}
1853 
1854 	Copy(&current_locale, &tmp, sizeof(LOCALE));
1855 }
1856 
1857 #define	COPY_LOCALE_STR(dest, size, src)	UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
1858 
1859 // Read the locale information
LoadLocale(LOCALE * locale,wchar_t * str)1860 bool LoadLocale(LOCALE *locale, wchar_t *str)
1861 {
1862 	UNI_TOKEN_LIST *tokens;
1863 	UINT i;
1864 	// Validate arguments
1865 	if (locale == NULL || str == NULL)
1866 	{
1867 		return false;
1868 	}
1869 
1870 	// Analysis of the token
1871 	tokens = UniParseToken(str, L" ");
1872 	if (tokens->NumTokens != 18)
1873 	{
1874 		UniFreeToken(tokens);
1875 		return false;
1876 	}
1877 
1878 	// Set to the structure
1879 	Zero(locale, sizeof(LOCALE));
1880 	COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
1881 	COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
1882 	COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
1883 	COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
1884 	COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
1885 	COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
1886 
1887 	for (i = 0;i < 7;i++)
1888 	{
1889 		COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
1890 			tokens->Token[6 + i]);
1891 	}
1892 
1893 	COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
1894 	COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
1895 	COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
1896 	COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
1897 
1898 	COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
1899 
1900 	UniFreeToken(tokens);
1901 	return true;
1902 }
1903 
1904 // Convert SYSTEMTIME into DOS date
SystemToDosDate(SYSTEMTIME * st)1905 USHORT SystemToDosDate(SYSTEMTIME *st)
1906 {
1907 	return (USHORT)(
1908 		((UINT)(st->wYear - 1980) << 9) |
1909 		((UINT)st->wMonth<< 5) |
1910 		(UINT)st->wDay);
1911 }
System64ToDosDate(UINT64 i)1912 USHORT System64ToDosDate(UINT64 i)
1913 {
1914 	SYSTEMTIME st;
1915 	UINT64ToSystem(&st, i);
1916 	return SystemToDosDate(&st);
1917 }
1918 
1919 // Convert SYSTEMTIME into DOS time
SystemToDosTime(SYSTEMTIME * st)1920 USHORT SystemToDosTime(SYSTEMTIME *st)
1921 {
1922 	return (USHORT)(
1923 		((UINT)st->wHour << 11) |
1924 		((UINT)st->wMinute << 5) |
1925 		((UINT)st->wSecond >> 1));
1926 }
System64ToDosTime(UINT64 i)1927 USHORT System64ToDosTime(UINT64 i)
1928 {
1929 	SYSTEMTIME st;
1930 	UINT64ToSystem(&st, i);
1931 	return SystemToDosTime(&st);
1932 }
1933 
1934 // Convert the tm to the SYSTEMTIME
TmToSystem(SYSTEMTIME * st,struct tm * t)1935 void TmToSystem(SYSTEMTIME *st, struct tm *t)
1936 {
1937 	struct tm tmp;
1938 	// Validate arguments
1939 	if (st == NULL || t == NULL)
1940 	{
1941 		return;
1942 	}
1943 
1944 	Copy(&tmp, t, sizeof(struct tm));
1945 	NormalizeTm(&tmp);
1946 
1947 	Zero(st, sizeof(SYSTEMTIME));
1948 	st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2099);
1949 	st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
1950 	st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
1951 	st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
1952 	st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
1953 	st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
1954 	st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
1955 	st->wMilliseconds = 0;
1956 }
1957 
1958 // Convert the SYSTEMTIME to tm
SystemToTm(struct tm * t,SYSTEMTIME * st)1959 void SystemToTm(struct tm *t, SYSTEMTIME *st)
1960 {
1961 	// Validate arguments
1962 	if (t == NULL || st == NULL)
1963 	{
1964 		return;
1965 	}
1966 
1967 	Zero(t, sizeof(struct tm));
1968 	t->tm_year = MAKESURE(st->wYear, 1970, 2099) - 1900;
1969 	t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
1970 	t->tm_mday = MAKESURE(st->wDay, 1, 31);
1971 	t->tm_hour = MAKESURE(st->wHour, 0, 23);
1972 	t->tm_min = MAKESURE(st->wMinute, 0, 59);
1973 	t->tm_sec = MAKESURE(st->wSecond, 0, 59);
1974 
1975 	t->tm_isdst = -1;
1976 	NormalizeTm(t);
1977 }
1978 
1979 // Convert the time_t to SYSTEMTIME
TimeToSystem(SYSTEMTIME * st,time_64t t)1980 void TimeToSystem(SYSTEMTIME *st, time_64t t)
1981 {
1982 	struct tm tmp;
1983 	// Validate arguments
1984 	if (st == NULL)
1985 	{
1986 		return;
1987 	}
1988 
1989 	TimeToTm(&tmp, t);
1990 	TmToSystem(st, &tmp);
1991 }
1992 
1993 // Convert the time_t to 64-bit SYSTEMTIME
TimeToSystem64(time_64t t)1994 UINT64 TimeToSystem64(time_64t t)
1995 {
1996 	SYSTEMTIME st;
1997 
1998 	TimeToSystem(&st, t);
1999 
2000 	return SystemToUINT64(&st);
2001 }
2002 
2003 // Convert the SYSTEMTIME to time_t
SystemToTime(SYSTEMTIME * st)2004 time_64t SystemToTime(SYSTEMTIME *st)
2005 {
2006 	struct tm t;
2007 	// Validate arguments
2008 	if (st == NULL)
2009 	{
2010 		return 0;
2011 	}
2012 
2013 	SystemToTm(&t, st);
2014 	return TmToTime(&t);
2015 }
2016 
2017 // Convert a 64-bit SYSTEMTIME to a time_t
System64ToTime(UINT64 i)2018 time_64t System64ToTime(UINT64 i)
2019 {
2020 	SYSTEMTIME st;
2021 
2022 	UINT64ToSystem(&st, i);
2023 
2024 	return SystemToTime(&st);
2025 }
2026 
2027 // Convert the tm to time_t
TmToTime(struct tm * t)2028 time_64t TmToTime(struct tm *t)
2029 {
2030 	time_64t tmp;
2031 	// Validate arguments
2032 	if (t == NULL)
2033 	{
2034 		return 0;
2035 	}
2036 
2037 	tmp = c_mkgmtime(t);
2038 	if (tmp == (time_64t)-1)
2039 	{
2040 		return 0;
2041 	}
2042 	return tmp;
2043 }
2044 
2045 // Convert time_t to tm
TimeToTm(struct tm * t,time_64t time)2046 void TimeToTm(struct tm *t, time_64t time)
2047 {
2048 	// Validate arguments
2049 	if (t == NULL)
2050 	{
2051 		return;
2052 	}
2053 
2054 	Zero(t, sizeof(struct tm));
2055 	c_gmtime_r(&time, t);
2056 }
2057 
2058 // Normalize the tm
NormalizeTm(struct tm * t)2059 void NormalizeTm(struct tm *t)
2060 {
2061 	time_64t tmp;
2062 	// Validate arguments
2063 	if (t == NULL)
2064 	{
2065 		return;
2066 	}
2067 
2068 	tmp = c_mkgmtime(t);
2069 	if (tmp == (time_64t)-1)
2070 	{
2071 		return;
2072 	}
2073 
2074 	c_gmtime_r(&tmp, t);
2075 }
2076 
2077 // Normalize the SYSTEMTIME
NormalizeSystem(SYSTEMTIME * st)2078 void NormalizeSystem(SYSTEMTIME *st)
2079 {
2080 	UINT64 sec64;
2081 	// Validate arguments
2082 	if (st == NULL)
2083 	{
2084 		return;
2085 	}
2086 
2087 	sec64 = SystemToUINT64(st);
2088 	UINT64ToSystem(st, sec64);
2089 }
2090 
2091 // Convert a 64-bit local time to a system time
LocalToSystem64(UINT64 t)2092 UINT64 LocalToSystem64(UINT64 t)
2093 {
2094 	SYSTEMTIME st;
2095 	UINT64ToSystem(&st, t);
2096 	LocalToSystem(&st, &st);
2097 	return SystemToUINT64(&st);
2098 }
2099 
2100 // Convert the 64bit system time to local time
SystemToLocal64(UINT64 t)2101 UINT64 SystemToLocal64(UINT64 t)
2102 {
2103 	SYSTEMTIME st;
2104 	UINT64ToSystem(&st, t);
2105 	SystemToLocal(&st, &st);
2106 	return SystemToUINT64(&st);
2107 }
2108 
2109 // Convert local time to system time
LocalToSystem(SYSTEMTIME * system,SYSTEMTIME * local)2110 void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
2111 {
2112 	UINT64 sec64;
2113 	// Validate arguments
2114 	if (local == NULL || system == NULL)
2115 	{
2116 		return;
2117 	}
2118 
2119 	sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
2120 	UINT64ToSystem(system, sec64);
2121 }
2122 
2123 // Convert the system time to local time
SystemToLocal(SYSTEMTIME * local,SYSTEMTIME * system)2124 void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
2125 {
2126 	UINT64 sec64;
2127 	// Validate arguments
2128 	if (local == NULL || system == NULL)
2129 	{
2130 		return;
2131 	}
2132 
2133 	sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
2134 	UINT64ToSystem(local, sec64);
2135 }
2136 
2137 // Get the time difference between the local time and the system time based on the specified time
GetTimeDiffEx(SYSTEMTIME * basetime,bool local_time)2138 INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
2139 {
2140 	time_t tmp;
2141 	struct tm t1, t2;
2142 	SYSTEMTIME snow;
2143 	struct tm now;
2144 	SYSTEMTIME s1, s2;
2145 	INT64 ret;
2146 
2147 	Copy(&snow, basetime, sizeof(SYSTEMTIME));
2148 
2149 	if (sizeof(time_t) == 4)
2150 	{
2151 		if (snow.wYear >= 2038)
2152 		{
2153 			// For old systems: avoid the 2038-year problem
2154 			snow.wYear = 2037;
2155 		}
2156 	}
2157 
2158 	SystemToTm(&now, &snow);
2159 	if (local_time == false)
2160 	{
2161 		tmp = (time_t)c_mkgmtime(&now);
2162 	}
2163 	else
2164 	{
2165 		tmp = mktime(&now);
2166 	}
2167 
2168 	if (tmp == (time_t)-1)
2169 	{
2170 		return 0;
2171 	}
2172 
2173 #ifndef	OS_UNIX
2174 	Copy(&t1, localtime(&tmp), sizeof(struct tm));
2175 	Copy(&t2, gmtime(&tmp), sizeof(struct tm));
2176 #else	// OS_UNIX
2177 	localtime_r(&tmp, &t1);
2178 	gmtime_r(&tmp, &t2);
2179 #endif	// OS_UNIX
2180 
2181 	TmToSystem(&s1, &t1);
2182 	TmToSystem(&s2, &t2);
2183 
2184 	ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
2185 
2186 	return ret;
2187 }
2188 
2189 // Convert UINT64 to the SYSTEMTIME
UINT64ToSystem(SYSTEMTIME * st,UINT64 sec64)2190 void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
2191 {
2192 	UINT64 tmp64;
2193 	UINT sec, millisec;
2194 	time_64t time;
2195 	// Validate arguments
2196 	if (st == NULL)
2197 	{
2198 		return;
2199 	}
2200 
2201 	sec64 = SafeTime64(sec64 + 32400000ULL);
2202 	tmp64 = sec64 / (UINT64)1000;
2203 	millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
2204 	sec = (UINT)tmp64;
2205 	time = (time_64t)sec;
2206 	TimeToSystem(st, time);
2207 	st->wMilliseconds = (WORD)millisec;
2208 }
2209 
2210 // Convert the SYSTEMTIME to UINT64
SystemToUINT64(SYSTEMTIME * st)2211 UINT64 SystemToUINT64(SYSTEMTIME *st)
2212 {
2213 	UINT64 sec64;
2214 	time_64t time;
2215 	// Validate arguments
2216 	if (st == NULL)
2217 	{
2218 		return 0;
2219 	}
2220 
2221 	time = SystemToTime(st);
2222 
2223 	//For times before 1970-01-01, clamp to the minimum
2224 	//because we have to return an unsigned integer.
2225 	//This is less wrong than casting it to UINT64
2226 	//and returning a time far in the future.
2227 	//For some reason we subtract 9 hours below, so
2228 	//account for that here.
2229 	if( time < 32400000LL ) return 0;
2230 
2231 	sec64 = (UINT64)time * (UINT64)1000;
2232 	sec64 += st->wMilliseconds;
2233 
2234 	return sec64 - 32400000ULL;
2235 }
2236 
2237 // Get local time in UINT64
LocalTime64()2238 UINT64 LocalTime64()
2239 {
2240 	SYSTEMTIME s;
2241 	LocalTime(&s);
2242 	return SystemToUINT64(&s);
2243 }
2244 
2245 // Get the system time in UINT64
SystemTime64()2246 UINT64 SystemTime64()
2247 {
2248 	SYSTEMTIME s;
2249 	SystemTime(&s);
2250 	return SystemToUINT64(&s);
2251 }
2252 
2253 // Get local time
LocalTime(SYSTEMTIME * st)2254 void LocalTime(SYSTEMTIME *st)
2255 {
2256 	SYSTEMTIME tmp;
2257 	// Validate arguments
2258 	if (st == NULL)
2259 	{
2260 		return;
2261 	}
2262 
2263 	SystemTime(&tmp);
2264 	SystemToLocal(st, &tmp);
2265 }
2266 
2267 // Get the System Time
SystemTime(SYSTEMTIME * st)2268 void SystemTime(SYSTEMTIME *st)
2269 {
2270 	// Validate arguments
2271 	if (st == NULL)
2272 	{
2273 		return;
2274 	}
2275 
2276 	OSGetSystemTime(st);
2277 
2278 	// KS
2279 	KS_INC(KS_GETTIME_COUNT);
2280 }
2281 
c_mkgmtime(struct tm * tm)2282 time_64t c_mkgmtime(struct tm *tm)
2283 {
2284 	int years, months, days, hours, minutes, seconds;
2285 
2286 	years = tm->tm_year + 1900;   /* year - 1900 -> year */
2287 	months = tm->tm_mon;          /* 0..11 */
2288 	days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
2289 	hours = tm->tm_hour;          /* 0..23 */
2290 	minutes = tm->tm_min;         /* 0..59 */
2291 	seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
2292 
2293 	ADJUST_TM(seconds, minutes, 60);
2294 	ADJUST_TM(minutes, hours, 60);
2295 	ADJUST_TM(hours, days, 24);
2296 	ADJUST_TM(months, years, 12);
2297 	if (days < 0)
2298 		do {
2299 			if (--months < 0) {
2300 				--years;
2301 				months = 11;
2302 			}
2303 			days += monthlen(months, years);
2304 		} while (days < 0);
2305 	else
2306 		while (days >= monthlen(months, years)) {
2307 			days -= monthlen(months, years);
2308 			if (++months >= 12) {
2309 				++years;
2310 				months = 0;
2311 			}
2312 		}
2313 
2314 		/* Restore adjusted values in tm structure */
2315 		tm->tm_year = years - 1900;
2316 		tm->tm_mon = months;
2317 		tm->tm_mday = days + 1;
2318 		tm->tm_hour = hours;
2319 		tm->tm_min = minutes;
2320 		tm->tm_sec = seconds;
2321 
2322 		/* Set `days' to the number of days into the year. */
2323 		days += ydays[months] + (months > 1 && leap (years));
2324 		tm->tm_yday = days;
2325 
2326 		/* Now calculate `days' to the number of days since Jan 1, 1970. */
2327 		days = (unsigned)days + 365 * (unsigned)(years - 1970) +
2328 			(unsigned)(nleap (years));
2329 		tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
2330 		tm->tm_isdst = 0;
2331 
2332 		if (years < 1970)
2333 			return (time_64t)-1;
2334 
2335 #if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
2336 #if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
2337 		if (years > TM_YEAR_MAX ||
2338 			(years == TM_YEAR_MAX &&
2339 			(tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
2340 			(TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
2341 			(tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
2342 			(TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
2343 			(hours > TM_HOUR_MAX ||
2344 			(hours == TM_HOUR_MAX &&
2345 			(minutes > TM_MIN_MAX ||
2346 			(minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
2347 			return (time_64t)-1;
2348 #endif
2349 #endif
2350 
2351 		return (time_64t)(86400L * (unsigned long)(unsigned)days +
2352 			3600L * (unsigned long)hours +
2353 			(unsigned long)(60 * minutes + seconds));
2354 }
2355 
2356 // Get the system timer
Tick()2357 UINT Tick()
2358 {
2359 	// KS
2360 	KS_INC(KS_GETTICK_COUNT);
2361 	return OSGetTick();
2362 }
2363 
2364 // Sleep thread
SleepThread(UINT time)2365 void SleepThread(UINT time)
2366 {
2367 	// KS
2368 	KS_INC(KS_SLEEPTHREAD_COUNT);
2369 
2370 	OSSleep(time);
2371 }
2372 
2373 // Yield
YieldCpu()2374 void YieldCpu()
2375 {
2376 	OSYield();
2377 }
2378 
2379 // Stop system (abnormal termination)
AbortExit()2380 void AbortExit()
2381 {
2382 #ifdef	OS_WIN32
2383 	_exit(1);
2384 #else	// OS_WIN32
2385 
2386 #ifdef	RLIMIT_CORE
2387 	UnixSetResourceLimit(RLIMIT_CORE, 0);
2388 #endif	// RLIMIT_CORE
2389 
2390 	abort();
2391 #endif	// OS_WIN32
2392 }
2393 
2394 
AbortExitEx(char * msg)2395 void AbortExitEx(char *msg)
2396 {
2397 	FILE *f;
2398 	// Validate arguments
2399 	if (msg == NULL)
2400 	{
2401 		msg = "Unknown Error";
2402 	}
2403 
2404 	f = fopen("abort_error_log.txt", "w");
2405 	if (f != NULL)
2406 	{
2407 		fwrite(msg, 1, strlen(msg), f);
2408 		fclose(f);
2409 	}
2410 
2411 	fputs("Fatal Error: ", stdout);
2412 	fputs(msg, stdout);
2413 	fputs("\r\n", stdout);
2414 
2415 #ifdef	OS_WIN32
2416 	_exit(1);
2417 #else	// OS_WIN32
2418 
2419 #ifdef	RLIMIT_CORE
2420 	UnixSetResourceLimit(RLIMIT_CORE, 0);
2421 #endif	// RLIMIT_CORE
2422 
2423 	abort();
2424 #endif	// OS_WIN32
2425 }
2426 
2427