1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
88 #include <Mayaqua/Mayaqua.h>
\r
91 #define TM_YEAR_MAX 2106
\r
94 #define TM_MON_MAX 1
\r
97 #define TM_MDAY_MAX 7
\r
100 #define TM_HOUR_MAX 6
\r
103 #define TM_MIN_MAX 28
\r
106 #define TM_SEC_MAX 14
\r
109 /* free mktime function
\r
110 Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
\r
111 and Michael Haertel <mike@ai.mit.edu>
\r
112 Unlimited distribution permitted provided this copyright notice is
\r
113 retained and any functional modifications are prominently identified. */
\r
114 #define ADJUST_TM(tm_member, tm_carry, modulus) \
\r
115 if ((tm_member) < 0){ \
\r
116 tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
\r
117 tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
\r
118 } else if ((tm_member) >= (modulus)) { \
\r
119 tm_carry += (tm_member) / (modulus); \
\r
120 tm_member = (tm_member) % (modulus); \
\r
122 #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
\r
123 #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
\r
124 #define leapday(m, y) ((m) == 1 && leap (y))
\r
125 #define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
\r
126 static int ydays[] =
\r
128 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
\r
132 static wchar_t *default_locale_str =
\r
133 L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
\r
135 static LOCALE current_locale;
\r
136 LOCK *tick_manual_lock = NULL;
\r
139 // リアルタイムシステムタイマの取得
\r
140 UINT TickRealtime()
\r
142 #if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES)
\r
145 return TickRealtimeManual() + 1;
\r
151 static UINT64 last_manual_tick = 0;
\r
152 static UINT64 manual_tick_add_value = 0;
\r
154 // clock_gettime が無いシステム向け (MacOS X など)
\r
155 UINT TickRealtimeManual()
\r
158 Lock(tick_manual_lock);
\r
160 ret = TickGetRealtimeTickValue64();
\r
162 if (last_manual_tick != 0 && (last_manual_tick > ret))
\r
164 manual_tick_add_value += (last_manual_tick - ret);
\r
167 last_manual_tick = ret;
\r
169 Unlock(tick_manual_lock);
\r
171 return (UINT)(ret + manual_tick_add_value);
\r
175 UINT64 TickGetRealtimeTickValue64()
\r
178 struct timezone tz;
\r
181 memset(&tv, 0, sizeof(tv));
\r
182 memset(&tz, 0, sizeof(tz));
\r
184 gettimeofday(&tv, &tz);
\r
186 ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
\r
194 void GetHomeDirW(wchar_t *path, UINT size)
\r
202 if (GetEnvW(L"HOME", path, size) == false)
\r
204 wchar_t drive[MAX_SIZE];
\r
205 wchar_t hpath[MAX_SIZE];
\r
206 if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
\r
207 GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
\r
209 UniFormat(path, sizeof(path), L"%s%s", drive, hpath);
\r
214 Win32GetCurrentDirW(path, size);
\r
216 UnixGetCurrentDirW(path, size);
\r
221 void GetHomeDir(char *path, UINT size)
\r
229 if (GetEnv("HOME", path, size) == false)
\r
231 char drive[MAX_SIZE];
\r
232 char hpath[MAX_SIZE];
\r
233 if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
\r
234 GetEnv("HOMEPATH", hpath, sizeof(hpath)))
\r
236 Format(path, sizeof(path), "%s%s", drive, hpath);
\r
241 Win32GetCurrentDir(path, size);
\r
243 UnixGetCurrentDir(path, size);
\r
250 bool GetEnv(char *name, char *data, UINT size)
\r
254 if (name == NULL || data == NULL)
\r
259 StrCpy(data, size, "");
\r
261 ret = getenv(name);
\r
267 StrCpy(data, size, ret);
\r
271 bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
\r
274 return GetEnvW_ForWin32(name, data, size);
\r
276 return GetEnvW_ForUnix(name, data, size);
\r
281 bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
\r
285 if (name == NULL || data == NULL)
\r
290 if (IsNt() == false)
\r
293 char *name_a = CopyUniToStr(name);
\r
294 char data_a[MAX_SIZE];
\r
296 ret = GetEnv(name_a, data_a, sizeof(data_a));
\r
300 StrToUni(data, size, data_a);
\r
308 UniStrCpy(data, size, L"");
\r
310 ret = _wgetenv(name);
\r
316 UniStrCpy(data, size, ret);
\r
325 bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
\r
329 char data_a[MAX_SIZE];
\r
331 if (name == NULL || data == NULL)
\r
336 name_a = CopyUniToUtf(name);
\r
338 ret = GetEnv(name_a, data_a, sizeof(data_a));
\r
342 UtfToUni(data, size, data_a);
\r
353 void GetMemInfo(MEMINFO *info)
\r
355 OSGetMemInfo(info);
\r
359 INSTANCE *NewSingleInstance(char *instance_name)
\r
361 return NewSingleInstanceEx(instance_name, false);
\r
363 INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
\r
365 char name[MAX_SIZE];
\r
369 if (instance_name != NULL)
\r
371 if (user_local == false)
\r
373 HashInstanceName(name, sizeof(name), instance_name);
\r
377 HashInstanceNameLocal(name, sizeof(name), instance_name);
\r
380 data = OSNewSingleInstance(name);
\r
384 data = OSNewSingleInstance(NULL);
\r
392 ret = ZeroMalloc(sizeof(INSTANCE));
\r
393 if (instance_name != NULL)
\r
395 ret->Name = CopyStr(instance_name);
\r
404 void FreeSingleInstance(INSTANCE *inst)
\r
412 OSFreeSingleInstance(inst->pData);
\r
414 if (inst->Name != NULL)
\r
422 void HashInstanceName(char *name, UINT size, char *instance_name)
\r
424 char tmp[MAX_SIZE];
\r
425 UCHAR hash[SHA1_SIZE];
\r
428 if (name == NULL || instance_name == NULL)
\r
433 StrCpy(tmp, sizeof(tmp), instance_name);
\r
437 Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
\r
438 BinToStr(key, sizeof(key), hash, 5);
\r
441 Format(name, size, "VPN-%s", key);
\r
443 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
\r
445 if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
\r
446 GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
\r
448 StrCpy(tmp, sizeof(tmp), name);
\r
449 Format(name, size, "Global\\%s", tmp);
\r
453 void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
\r
455 char tmp[MAX_SIZE];
\r
456 UCHAR hash[SHA1_SIZE];
\r
459 if (name == NULL || instance_name == NULL)
\r
464 StrCpy(tmp, sizeof(tmp), instance_name);
\r
468 Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
\r
469 BinToStr(key, sizeof(key), hash, 5);
\r
472 Format(name, size, "VPN-%s", key);
\r
474 if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
\r
476 if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
\r
477 GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
\r
479 StrCpy(tmp, sizeof(tmp), name);
\r
480 Format(name, size, "Local\\%s", tmp);
\r
486 bool Run(char *filename, char *arg, bool hide, bool wait)
\r
489 if (filename == NULL)
\r
494 return OSRun(filename, arg, hide, wait);
\r
496 bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
\r
499 if (filename == NULL)
\r
504 return OSRunW(filename, arg, hide, wait);
\r
508 void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
\r
510 char tmp[MAX_SIZE];
\r
516 GetDateTimeStr64(tmp, sizeof(tmp), sec64);
\r
517 StrToUni(str, size, tmp);
\r
519 void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
\r
522 UINT64ToSystem(&st, sec64);
\r
523 GetDateTimeStr(str, size, &st);
\r
525 void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
\r
528 UINT64ToSystem(&st, sec64);
\r
529 GetDateTimeStrMilli(str, size, &st);
\r
531 void GetDateStr64(char *str, UINT size, UINT64 sec64)
\r
536 StrCpy(str, size, "(Unknown)");
\r
539 UINT64ToSystem(&st, sec64);
\r
540 GetDateStr(str, size, &st);
\r
542 void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
\r
545 if (locale == NULL)
\r
547 locale = ¤t_locale;
\r
549 if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
\r
551 UniStrCpy(str, size, locale->Unknown);
\r
554 UINT64ToSystem(&st, sec64);
\r
555 GetDateTimeStrEx(str, size, &st, locale);
\r
557 void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
\r
560 if (locale == NULL)
\r
562 locale = ¤t_locale;
\r
564 if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
\r
566 UniStrCpy(str, size, locale->Unknown);
\r
569 UINT64ToSystem(&st, sec64);
\r
570 GetTimeStrEx(str, size, &st, locale);
\r
572 void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
\r
575 if (locale == NULL)
\r
577 locale = ¤t_locale;
\r
579 if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
\r
581 UniStrCpy(str, size, locale->Unknown);
\r
584 UINT64ToSystem(&st, sec64);
\r
585 GetDateStrEx(str, size, &st, locale);
\r
587 void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
\r
590 if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
\r
592 StrCpy(str, size, "(Unknown)");
\r
595 UINT64ToSystem(&st, sec64);
\r
596 GetTimeStrMilli(str, size, &st);
\r
598 void GetTimeStr64(char *str, UINT size, UINT64 sec64)
\r
601 if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
\r
603 StrCpy(str, size, "(Unknown)");
\r
606 UINT64ToSystem(&st, sec64);
\r
607 GetTimeStr(str, size, &st);
\r
610 // 現在の POSIX 実装で使用しても安全な時刻に変換する
\r
611 UINT64 SafeTime64(UINT64 sec64)
\r
613 return MAKESURE(sec64, 0, 2115947647000ULL);
\r
617 static SK *thread_pool = NULL;
\r
618 static COUNTER *thread_count = NULL;
\r
621 void InitThreading()
\r
623 thread_pool = NewSk();
\r
624 thread_count = NewCounter();
\r
628 void FreeThreading()
\r
632 if (Count(thread_count) == 0)
\r
642 THREAD_POOL_DATA *pd;
\r
643 THREAD *t = Pop(thread_pool);
\r
650 pd = (THREAD_POOL_DATA *)t->param;
\r
652 pd->ThreadProc = NULL;
\r
655 WaitThreadInternal(t);
\r
657 pd = (THREAD_POOL_DATA *)t->param;
\r
658 ReleaseEvent(pd->Event);
\r
659 ReleaseEvent(pd->InitFinishEvent);
\r
661 ReleaseThreadInternal(t);
\r
666 ReleaseSk(thread_pool);
\r
668 DeleteCounter(thread_count);
\r
669 thread_count = NULL;
\r
673 void ThreadPoolProc(THREAD *t, void *param)
\r
675 THREAD_POOL_DATA *pd;
\r
682 pd = (THREAD_POOL_DATA *)param;
\r
684 NoticeThreadInitInternal(t);
\r
693 Wait(pd->Event, INFINITE);
\r
695 if (pd->ThreadProc == NULL)
\r
701 thread = pd->Thread;
\r
702 thread->ThreadId = ThreadId();
\r
705 Set(pd->InitFinishEvent);
\r
708 pd->ThreadProc(pd->Thread, thread->param);
\r
710 thread->PoolHalting = true;
\r
713 LockList(thread->PoolWaitList);
\r
715 num = LIST_NUM(thread->PoolWaitList);
\r
716 ee = ToArray(thread->PoolWaitList);
\r
718 DeleteAll(thread->PoolWaitList);
\r
720 UnlockList(thread->PoolWaitList);
\r
722 for (i = 0;i < num;i++)
\r
734 if (Count(thread->ref->c) <= 1)
\r
739 Wait(thread->release_event, 256);
\r
742 ReleaseThread(thread);
\r
745 // Win32 の場合: スレッドの優先順位を元に戻す
\r
746 MsRestoreThreadPriority();
\r
749 // スレッドプールに自分自身を登録する
\r
750 LockSk(thread_pool);
\r
752 Push(thread_pool, t);
\r
754 UnlockSk(thread_pool);
\r
767 THREAD *NewThread(THREAD_PROC *thread_proc, void *param)
\r
769 THREAD *host = NULL;
\r
770 THREAD_POOL_DATA *pd = NULL;
\r
772 bool new_thread = false;
\r
774 if (thread_proc == NULL)
\r
779 if (IsTrackingEnabled() == false)
\r
786 LockSk(thread_pool);
\r
788 // 現在プールに空いているスレッドがあるかどうか調べる
\r
789 host = Pop(thread_pool);
\r
791 UnlockSk(thread_pool);
\r
795 // 空いているスレッドが見つからなかったので新しいスレッドを作成する
\r
796 pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
\r
797 pd->Event = NewEvent();
\r
798 pd->InitFinishEvent = NewEvent();
\r
799 host = NewThreadInternal(ThreadPoolProc, pd);
\r
800 WaitThreadInitInternal(host);
\r
806 pd = (THREAD_POOL_DATA *)host->param;
\r
810 ret = ZeroMalloc(sizeof(THREAD));
\r
811 ret->ref = NewRef();
\r
812 ret->thread_proc = thread_proc;
\r
813 ret->param = param;
\r
815 ret->init_finished_event = NewEvent();
\r
816 ret->PoolThread = true;
\r
817 ret->PoolWaitList = NewList(NULL);
\r
818 ret->PoolHostThread = host;
\r
819 ret->release_event = NewEvent();
\r
822 pd->ThreadProc = thread_proc;
\r
828 Wait(pd->InitFinishEvent, INFINITE);
\r
833 // スレッドのクリーンアップ (プール)
\r
834 void CleanupThread(THREAD *t)
\r
842 ReleaseEvent(t->init_finished_event);
\r
843 ReleaseEvent(t->release_event);
\r
844 ReleaseList(t->PoolWaitList);
\r
850 void ReleaseThread(THREAD *t)
\r
860 e = t->release_event;
\r
866 ret = Release(t->ref);
\r
877 // スレッドの初期化完了を通知 (プール)
\r
878 void NoticeThreadInit(THREAD *t)
\r
887 Set(t->init_finished_event);
\r
890 // スレッドの初期化完了を待機 (プール)
\r
891 void WaitThreadInit(THREAD *t)
\r
900 KS_INC(KS_WAITFORTHREAD_COUNT);
\r
903 Wait(t->init_finished_event, INFINITE);
\r
906 // スレッドの終了を待機 (プール)
\r
907 bool WaitThread(THREAD *t, UINT timeout)
\r
917 LockList(t->PoolWaitList);
\r
919 if (t->PoolHalting)
\r
926 // 終了時通知イベントをリストに登録する
\r
929 Insert(t->PoolWaitList, e);
\r
932 UnlockList(t->PoolWaitList);
\r
937 ret = Wait(e, timeout);
\r
939 LockList(t->PoolWaitList);
\r
941 if (Delete(t->PoolWaitList, e))
\r
946 UnlockList(t->PoolWaitList);
\r
957 return OSThreadId();
\r
961 THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
\r
966 if (thread_proc == NULL)
\r
972 t = ZeroMalloc(sizeof(THREAD));
\r
973 t->init_finished_event = NewEvent();
\r
977 t->thread_proc = thread_proc;
\r
979 // OS がスレッドを初期化するまで待機
\r
982 if ((retry++) > 60)
\r
984 printf("\n\n*** error: new thread create failed.\n\n");
\r
987 if (OSInitThread(t))
\r
995 KS_INC(KS_NEWTHREAD_COUNT);
\r
1001 void ReleaseThreadInternal(THREAD *t)
\r
1009 if (Release(t->ref) == 0)
\r
1011 CleanupThreadInternal(t);
\r
1016 void CleanupThreadInternal(THREAD *t)
\r
1028 ReleaseEvent(t->init_finished_event);
\r
1033 KS_INC(KS_FREETHREAD_COUNT);
\r
1037 bool WaitThreadInternal(THREAD *t)
\r
1045 return OSWaitThread(t);
\r
1048 // スレッドの初期化が完了したことを通知する
\r
1049 void NoticeThreadInitInternal(THREAD *t)
\r
1058 Set(t->init_finished_event);
\r
1061 // スレッドの初期化が完了するまで待機する
\r
1062 void WaitThreadInitInternal(THREAD *t)
\r
1071 KS_INC(KS_WAITFORTHREAD_COUNT);
\r
1074 Wait(t->init_finished_event, INFINITE);
\r
1077 // 日時文字列をロケール情報を使用して取得
\r
1078 void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
\r
1080 wchar_t tmp1[MAX_SIZE];
\r
1081 wchar_t tmp2[MAX_SIZE];
\r
1083 if (str == NULL || st == NULL)
\r
1088 GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
\r
1089 GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
\r
1090 UniFormat(str, size, L"%s %s", tmp1, tmp2);
\r
1093 // 時刻文字列をロケール情報を使用して取得
\r
1094 void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
\r
1096 wchar_t *tag = L"%02u%s%02u%s%02u%s";
\r
1098 if (str == NULL || st == NULL)
\r
1103 if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
\r
1105 tag = L"%2u%s%2u%s%2u%s";
\r
1108 locale = (locale != NULL ? locale : ¤t_locale);
\r
1109 UniFormat(str, size,
\r
1111 st->wHour, locale->HourStr,
\r
1112 st->wMinute, locale->MinuteStr,
\r
1113 st->wSecond, locale->SecondStr);
\r
1116 // 日付文字列をロケール情報を使用して取得
\r
1117 void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
\r
1119 wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
\r
1121 if (str == NULL || st == NULL)
\r
1126 if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
\r
1128 tag = L"%4u%s%2u%s%2u%s(%s)";
\r
1131 locale = (locale != NULL ? locale : ¤t_locale);
\r
1132 UniFormat(str, size,
\r
1134 st->wYear, locale->YearStr,
\r
1135 st->wMonth, locale->MonthStr,
\r
1136 st->wDay, locale->DayStr,
\r
1137 locale->DayOfWeek[st->wDayOfWeek]);
\r
1140 // 時刻文字列をミリ秒単位で取得 (例: 12:34:56.789)
\r
1141 void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
\r
1144 if (st == NULL || str == NULL)
\r
1149 Format(str, size, "%02u:%02u:%02u.%03u",
\r
1150 st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
\r
1153 // 時刻文字列を取得 (例: 12:34:56)
\r
1154 void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
\r
1157 if (str == NULL || st == NULL)
\r
1162 Format(str, size, "%02u:%02u:%02u",
\r
1163 st->wHour, st->wMinute, st->wSecond);
\r
1166 // 日付文字列を取得 (例: 2004/07/23)
\r
1167 void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
\r
1170 if (str == NULL || st == NULL)
\r
1175 Format(str, size, "%04u-%02u-%02u",
\r
1176 st->wYear, st->wMonth, st->wDay);
\r
1179 // 日時文字列を取得 (例: 2004/07/23 12:34:56)
\r
1180 void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
\r
1183 if (str == NULL || st == NULL)
\r
1188 Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
\r
1189 st->wYear, st->wMonth, st->wDay,
\r
1190 st->wHour, st->wMinute, st->wSecond);
\r
1193 // 日時文字列をミリ秒単位で取得 (例: 2004/07/23 12:34:56.789)
\r
1194 void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
\r
1197 if (str == NULL || st == NULL)
\r
1202 Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
\r
1203 st->wYear, st->wMonth, st->wDay,
\r
1204 st->wHour, st->wMinute, st->wSecond,
\r
1205 st->wMilliseconds);
\r
1209 void GetSpanStr(char *str, UINT size, UINT64 sec64)
\r
1211 char tmp[MAX_SIZE];
\r
1218 StrCpy(tmp, sizeof(tmp), "");
\r
1219 if (sec64 >= (UINT64)(1000 * 3600 * 24))
\r
1221 Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
\r
1224 Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
\r
1225 (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
\r
1226 (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
\r
1227 (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
\r
1230 StrCpy(str, size, tmp);
\r
1233 // 時間文字列の取得 (ミリ秒単位)
\r
1234 void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
\r
1236 char tmp[MAX_SIZE];
\r
1243 StrCpy(tmp, sizeof(tmp), "");
\r
1244 if (sec64 >= (UINT64)(1000 * 3600 * 24))
\r
1246 Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
\r
1249 Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
\r
1250 (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
\r
1251 (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
\r
1252 (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
\r
1253 (UINT)(sec64 % (UINT64)(1000)));
\r
1256 StrCpy(str, size, tmp);
\r
1260 void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
\r
1262 wchar_t tmp[MAX_SIZE];
\r
1269 locale = (locale != NULL ? locale : ¤t_locale);
\r
1271 UniStrCpy(tmp, sizeof(tmp), L"");
\r
1272 if (sec64 >= (UINT64)(1000 * 3600 * 24))
\r
1274 UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
\r
1278 UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
\r
1279 (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
\r
1281 (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
\r
1282 locale->SpanMinute,
\r
1283 (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
\r
1284 locale->SpanSecond);
\r
1287 UniStrCpy(str, size, tmp);
\r
1291 void GetCurrentLocale(LOCALE *locale)
\r
1294 if (locale == NULL)
\r
1299 Copy(locale, ¤t_locale, sizeof(LOCALE));
\r
1303 void SetLocale(wchar_t *str)
\r
1305 wchar_t *set_locale_str;
\r
1310 set_locale_str = str;
\r
1314 set_locale_str = default_locale_str;
\r
1317 if (LoadLocale(&tmp, set_locale_str) == false)
\r
1319 if (LoadLocale(&tmp, default_locale_str) == false)
\r
1325 Copy(¤t_locale, &tmp, sizeof(LOCALE));
\r
1328 #define COPY_LOCALE_STR(dest, size, src) UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
\r
1331 bool LoadLocale(LOCALE *locale, wchar_t *str)
\r
1333 UNI_TOKEN_LIST *tokens;
\r
1336 if (locale == NULL || str == NULL)
\r
1342 tokens = UniParseToken(str, L" ");
\r
1343 if (tokens->NumTokens != 18)
\r
1345 UniFreeToken(tokens);
\r
1350 Zero(locale, sizeof(LOCALE));
\r
1351 COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
\r
1352 COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
\r
1353 COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
\r
1354 COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
\r
1355 COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
\r
1356 COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
\r
1358 for (i = 0;i < 7;i++)
\r
1360 COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
\r
1361 tokens->Token[6 + i]);
\r
1364 COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
\r
1365 COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
\r
1366 COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
\r
1367 COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
\r
1369 COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
\r
1371 UniFreeToken(tokens);
\r
1375 // tm を SYSTEMTIME に変換
\r
1376 void TmToSystem(SYSTEMTIME *st, struct tm *t)
\r
1380 if (st == NULL || t == NULL)
\r
1385 Copy(&tmp, t, sizeof(struct tm));
\r
1386 NormalizeTm(&tmp);
\r
1388 Zero(st, sizeof(SYSTEMTIME));
\r
1389 st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2037);
\r
1390 st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
\r
1391 st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
\r
1392 st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
\r
1393 st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
\r
1394 st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
\r
1395 st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
\r
1396 st->wMilliseconds = 0;
\r
1399 // SYSTEMTIME を tm に変換
\r
1400 void SystemToTm(struct tm *t, SYSTEMTIME *st)
\r
1403 if (t == NULL || st == NULL)
\r
1408 Zero(t, sizeof(struct tm));
\r
1409 t->tm_year = MAKESURE(st->wYear, 1970, 2037) - 1900;
\r
1410 t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
\r
1411 t->tm_mday = MAKESURE(st->wDay, 1, 31);
\r
1412 t->tm_hour = MAKESURE(st->wHour, 0, 23);
\r
1413 t->tm_min = MAKESURE(st->wMinute, 0, 59);
\r
1414 t->tm_sec = MAKESURE(st->wSecond, 0, 59);
\r
1420 // time_t を SYSTEMTIME に変換
\r
1421 void TimeToSystem(SYSTEMTIME *st, time_t t)
\r
1430 TimeToTm(&tmp, t);
\r
1431 TmToSystem(st, &tmp);
\r
1434 // SYSTEMTIME を time_t に変換
\r
1435 time_t SystemToTime(SYSTEMTIME *st)
\r
1444 SystemToTm(&t, st);
\r
1445 return TmToTime(&t);
\r
1448 // tm を time_t に変換
\r
1449 time_t TmToTime(struct tm *t)
\r
1458 tmp = c_mkgmtime(t);
\r
1459 if (tmp == (time_t)-1)
\r
1466 // time_t を tm に変換
\r
1467 void TimeToTm(struct tm *t, time_t time)
\r
1477 ret = gmtime(&time);
\r
1479 ret = malloc(sizeof(struct tm));
\r
1480 memset(ret, 0, sizeof(ret));
\r
1481 gmtime_r(&time, ret);
\r
1486 Zero(t, sizeof(struct tm));
\r
1490 Copy(t, ret, sizeof(struct tm));
\r
1499 void NormalizeTm(struct tm *t)
\r
1509 tmp = c_mkgmtime(t);
\r
1510 if (tmp == (time_t)-1)
\r
1516 ret = gmtime(&tmp);
\r
1518 ret = malloc(sizeof(struct tm));
\r
1519 memset(ret, 0, sizeof(ret));
\r
1520 gmtime_r(&tmp, ret);
\r
1525 Zero(t, sizeof(struct tm));
\r
1529 Copy(t, ret, sizeof(struct tm));
\r
1537 // SYSTEMTIME を正規化
\r
1538 void NormalizeSystem(SYSTEMTIME *st)
\r
1547 sec64 = SystemToUINT64(st);
\r
1548 UINT64ToSystem(st, sec64);
\r
1551 // 64bit ローカル時刻をシステム時刻に変換
\r
1552 UINT64 LocalToSystem64(UINT64 t)
\r
1555 UINT64ToSystem(&st, t);
\r
1556 LocalToSystem(&st, &st);
\r
1557 return SystemToUINT64(&st);
\r
1560 // 64bit システム時刻をローカル時刻に変換
\r
1561 UINT64 SystemToLocal64(UINT64 t)
\r
1564 UINT64ToSystem(&st, t);
\r
1565 SystemToLocal(&st, &st);
\r
1566 return SystemToUINT64(&st);
\r
1569 // ローカル時刻をシステム時刻に変換
\r
1570 void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
\r
1574 if (local == NULL || system == NULL)
\r
1579 sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
\r
1580 UINT64ToSystem(system, sec64);
\r
1583 // システム時刻をローカル時刻に変換
\r
1584 void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
\r
1588 if (local == NULL || system == NULL)
\r
1593 sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
\r
1594 UINT64ToSystem(local, sec64);
\r
1597 // 指定時刻をベースにしてシステム時刻とローカル時刻との間の時差を取得
\r
1598 INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
\r
1604 SYSTEMTIME s1, s2;
\r
1607 Copy(&snow, basetime, sizeof(SYSTEMTIME));
\r
1609 SystemToTm(&now, &snow);
\r
1610 if (local_time == false)
\r
1612 tmp = c_mkgmtime(&now);
\r
1616 tmp = mktime(&now);
\r
1619 if (tmp == (time_t)-1)
\r
1624 Copy(&t1, localtime(&tmp), sizeof(struct tm));
\r
1625 Copy(&t2, gmtime(&tmp), sizeof(struct tm));
\r
1626 TmToSystem(&s1, &t1);
\r
1627 TmToSystem(&s2, &t2);
\r
1629 ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
\r
1634 // システム時刻とローカル時刻との間の時差を取得
\r
1635 INT64 GetTimeDiff()
\r
1641 SYSTEMTIME s1, s2;
\r
1644 static INT64 cache = INFINITE;
\r
1646 if (cache != INFINITE)
\r
1648 // 1 度測定したらキャッシュデータを返す
\r
1652 SystemTime(&snow);
\r
1653 SystemToTm(&now, &snow);
\r
1654 tmp = c_mkgmtime(&now);
\r
1655 if (tmp == (time_t)-1)
\r
1660 Copy(&t1, localtime(&tmp), sizeof(struct tm));
\r
1661 Copy(&t2, gmtime(&tmp), sizeof(struct tm));
\r
1662 TmToSystem(&s1, &t1);
\r
1663 TmToSystem(&s2, &t2);
\r
1665 cache = ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
\r
1670 // UINT64 を SYSTEMTIME に変換
\r
1671 void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
\r
1674 UINT sec, millisec;
\r
1682 sec64 = SafeTime64(sec64 + 32400000ULL);
\r
1683 tmp64 = sec64 / (UINT64)1000;
\r
1684 millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
\r
1685 sec = (UINT)tmp64;
\r
1686 time = (time_t)sec;
\r
1687 TimeToSystem(st, time);
\r
1688 st->wMilliseconds = (WORD)millisec;
\r
1691 // SYSTEMTIME を UINT64 に変換
\r
1692 UINT64 SystemToUINT64(SYSTEMTIME *st)
\r
1702 time = SystemToTime(st);
\r
1703 sec64 = (UINT64)time * (UINT64)1000;
\r
1704 sec64 += st->wMilliseconds;
\r
1706 return sec64 - 32400000ULL;
\r
1709 // ローカル時刻を UINT64 で取得
\r
1710 UINT64 LocalTime64()
\r
1714 return SystemToUINT64(&s);
\r
1717 // システム時刻を UINT64 で取得
\r
1718 UINT64 SystemTime64()
\r
1722 return SystemToUINT64(&s);
\r
1726 void LocalTime(SYSTEMTIME *st)
\r
1736 SystemToLocal(st, &tmp);
\r
1740 void SystemTime(SYSTEMTIME *st)
\r
1748 OSGetSystemTime(st);
\r
1751 KS_INC(KS_GETTIME_COUNT);
\r
1754 /* free mktime function
\r
1755 Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
\r
1756 and Michael Haertel <mike@ai.mit.edu>
\r
1757 Unlimited distribution permitted provided this copyright notice is
\r
1758 retained and any functional modifications are prominently identified. */
\r
1759 time_t c_mkgmtime(struct tm *tm)
\r
1761 int years, months, days, hours, minutes, seconds;
\r
1763 years = tm->tm_year + 1900; /* year - 1900 -> year */
\r
1764 months = tm->tm_mon; /* 0..11 */
\r
1765 days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
\r
1766 hours = tm->tm_hour; /* 0..23 */
\r
1767 minutes = tm->tm_min; /* 0..59 */
\r
1768 seconds = tm->tm_sec; /* 0..61 in ANSI C. */
\r
1770 ADJUST_TM(seconds, minutes, 60);
\r
1771 ADJUST_TM(minutes, hours, 60);
\r
1772 ADJUST_TM(hours, days, 24);
\r
1773 ADJUST_TM(months, years, 12);
\r
1776 if (--months < 0) {
\r
1780 days += monthlen(months, years);
\r
1781 } while (days < 0);
\r
1783 while (days >= monthlen(months, years)) {
\r
1784 days -= monthlen(months, years);
\r
1785 if (++months >= 12) {
\r
1791 /* Restore adjusted values in tm structure */
\r
1792 tm->tm_year = years - 1900;
\r
1793 tm->tm_mon = months;
\r
1794 tm->tm_mday = days + 1;
\r
1795 tm->tm_hour = hours;
\r
1796 tm->tm_min = minutes;
\r
1797 tm->tm_sec = seconds;
\r
1799 /* Set `days' to the number of days into the year. */
\r
1800 days += ydays[months] + (months > 1 && leap (years));
\r
1801 tm->tm_yday = days;
\r
1803 /* Now calculate `days' to the number of days since Jan 1, 1970. */
\r
1804 days = (unsigned)days + 365 * (unsigned)(years - 1970) +
\r
1805 (unsigned)(nleap (years));
\r
1806 tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
\r
1810 return (time_t)-1;
\r
1812 #if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
\r
1813 #if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
\r
1814 if (years > TM_YEAR_MAX ||
\r
1815 (years == TM_YEAR_MAX &&
\r
1816 (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
\r
1817 (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
\r
1818 (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
\r
1819 (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
\r
1820 (hours > TM_HOUR_MAX ||
\r
1821 (hours == TM_HOUR_MAX &&
\r
1822 (minutes > TM_MIN_MAX ||
\r
1823 (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
\r
1824 return (time_t)-1;
\r
1828 return (time_t)(86400L * (unsigned long)(unsigned)days +
\r
1829 3600L * (unsigned long)hours +
\r
1830 (unsigned long)(60 * minutes + seconds));
\r
1837 KS_INC(KS_GETTICK_COUNT);
\r
1838 return OSGetTick();
\r
1842 void SleepThread(UINT time)
\r
1845 KS_INC(KS_SLEEPTHREAD_COUNT);
\r
1863 #ifdef RLIMIT_CORE
\r
1864 UnixSetResourceLimit(RLIMIT_CORE, 0);
\r
1865 #endif // RLIMIT_CORE
\r
1868 #endif // OS_WIN32
\r
1872 void AbortExitEx(char *msg)
\r
1878 msg = "Unknown Error";
\r
1881 f = fopen("abort_error_log.txt", "w");
\r
1884 fwrite(msg, 1, strlen(msg), f);
\r
1888 fputs("Fatal Error: ", stdout);
\r
1889 fputs(msg, stdout);
\r
1890 fputs("\r\n", stdout);
\r
1896 #ifdef RLIMIT_CORE
\r
1897 UnixSetResourceLimit(RLIMIT_CORE, 0);
\r
1898 #endif // RLIMIT_CORE
\r
1901 #endif // OS_WIN32
\r