12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450 |
- // SoftEther VPN Source Code - Stable Edition Repository
- // Mayaqua Kernel
- //
- // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
- //
- // Copyright (c) Daiyuu Nobori.
- // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
- // Copyright (c) SoftEther Corporation.
- // Copyright (c) all contributors on SoftEther VPN project in GitHub.
- //
- // All Rights Reserved.
- //
- // http://www.softether.org/
- //
- // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
- // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
- // Contributors:
- // - nattoheaven (https://github.com/nattoheaven)
- //
- // License: The Apache License, Version 2.0
- // https://www.apache.org/licenses/LICENSE-2.0
- //
- // DISCLAIMER
- // ==========
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
- //
- // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
- // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
- // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
- // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
- // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
- // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
- // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
- // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
- // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
- // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
- // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
- // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
- // LAW OR COURT RULE.
- //
- // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
- // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
- // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
- // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
- // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
- // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
- // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
- // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
- // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
- // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
- // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
- // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
- // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
- // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
- // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
- // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
- // STATEMENT FOR WARNING AND DISCLAIMER.
- //
- // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
- // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
- // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
- //
- //
- // SOURCE CODE CONTRIBUTION
- // ------------------------
- //
- // Your contribution to SoftEther VPN Project is much appreciated.
- // Please send patches to us through GitHub.
- // Read the SoftEther VPN Patch Acceptance Policy in advance:
- // http://www.softether.org/5-download/src/9.patch
- //
- //
- // DEAR SECURITY EXPERTS
- // ---------------------
- //
- // If you find a bug or a security vulnerability please kindly inform us
- // about the problem immediately so that we can fix the security problem
- // to protect a lot of users around the world as soon as possible.
- //
- // Our e-mail address for security reports is:
- // softether-vpn-security [at] softether.org
- //
- // Please note that the above e-mail address is not a technical support
- // inquiry address. If you need technical assistance, please visit
- // http://www.softether.org/ and ask your question on the users forum.
- //
- // Thank you for your cooperation.
- //
- //
- // NO MEMORY OR RESOURCE LEAKS
- // ---------------------------
- //
- // The memory-leaks and resource-leaks verification under the stress
- // test has been passed before release this source code.
- // Kernel.c
- // System service processing routine
- #include <GlobalConst.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <wchar.h>
- #include <stdarg.h>
- #include <time.h>
- #include <errno.h>
- #include <Mayaqua/Mayaqua.h>
- #ifndef TM_YEAR_MAX
- #define TM_YEAR_MAX 2106
- #endif
- #ifndef TM_MON_MAX
- #define TM_MON_MAX 1
- #endif
- #ifndef TM_MDAY_MAX
- #define TM_MDAY_MAX 7
- #endif
- #ifndef TM_HOUR_MAX
- #define TM_HOUR_MAX 6
- #endif
- #ifndef TM_MIN_MAX
- #define TM_MIN_MAX 28
- #endif
- #ifndef TM_SEC_MAX
- #define TM_SEC_MAX 14
- #endif
- #define ADJUST_TM(tm_member, tm_carry, modulus) \
- if ((tm_member) < 0){ \
- tm_carry -= (1 - ((tm_member)+1) / (modulus)); \
- tm_member = (modulus-1) + (((tm_member)+1) % (modulus)); \
- } else if ((tm_member) >= (modulus)) { \
- tm_carry += (tm_member) / (modulus); \
- tm_member = (tm_member) % (modulus); \
- }
- #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
- #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
- #define leapday(m, y) ((m) == 1 && leap (y))
- #define monthlen(m, y) (ydays[(m)+1] - ydays[m] + leapday (m, y))
- static int ydays[] =
- {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
- };
- static UINT current_num_thread = 0;
- static UINT cached_number_of_cpus = 0;
- static wchar_t *default_locale_str =
- L"- - $ : : $ Sun Mon Tue Wed Thu Fri Sat : : : $ (None)";
- static LOCALE current_locale;
- LOCK *tick_manual_lock = NULL;
- UINT g_zero = 0;
- #define MONSPERYEAR 12
- #define DAYSPERNYEAR 365
- #define DAYSPERLYEAR 366
- #define SECSPERMIN 60
- #define SECSPERHOUR (60*60)
- #define SECSPERDAY (24*60*60)
- #define DAYSPERWEEK 7
- #define TM_SUNDAY 0
- #define TM_MONDAY 1
- #define TM_TUESDAY 2
- #define TM_WEDNESDAY 3
- #define TM_THURSDAY 4
- #define TM_FRIDAY 5
- #define TM_SATURDAY 6
- #define TM_YEAR_BASE 1900
- #define EPOCH_YEAR 1970
- #define EPOCH_WDAY TM_THURSDAY
- #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
- static const int mon_lengths[2][MONSPERYEAR] = {
- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
- };
- static const int year_lengths[2] = {
- DAYSPERNYEAR, DAYSPERLYEAR
- };
- /*
- * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
- * localtime.c 7.78.
- * tzfile.h 1.8
- * adapted to be replacement gmtime_r.
- */
- static void
- c_timesub(timep, offset, tmp)
- const time_64t * const timep;
- const long offset;
- struct tm * const tmp;
- {
- INT64 days;
- INT64 rem;
- INT64 y;
- int yleap;
- const int * ip;
- days = *timep / SECSPERDAY;
- rem = *timep % SECSPERDAY;
- rem += (offset);
- while (rem < 0) {
- rem += SECSPERDAY;
- --days;
- }
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++days;
- }
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
- rem = rem % SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec = (int) (rem % SECSPERMIN) ;
- tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
- if (tmp->tm_wday < 0)
- tmp->tm_wday += DAYSPERWEEK;
- y = EPOCH_YEAR;
- #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
- while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
- INT64 newy;
- newy = y + days / DAYSPERNYEAR;
- if (days < 0)
- --newy;
- days -= (newy - y) * DAYSPERNYEAR +
- LEAPS_THRU_END_OF(newy - 1) -
- LEAPS_THRU_END_OF(y - 1);
- y = newy;
- }
- tmp->tm_year = (int)(y - TM_YEAR_BASE);
- tmp->tm_yday = (int) days;
- ip = mon_lengths[yleap];
- for (tmp->tm_mon = 0; days >= (INT64) ip[tmp->tm_mon]; ++(tmp->tm_mon))
- days = days - (INT64) ip[tmp->tm_mon];
- tmp->tm_mday = (int) (days + 1);
- tmp->tm_isdst = 0;
- }
- /*
- * Re-entrant version of gmtime.
- */
- struct tm * c_gmtime_r(const time_64t* timep, struct tm *tm)
- {
- c_timesub(timep, 0L, tm);
- return tm;
- }
- // Get the real-time system timer
- UINT TickRealtime()
- {
- #if defined(OS_WIN32) || defined(CLOCK_REALTIME) || defined(CLOCK_MONOTONIC) || defined(CLOCK_HIGHRES) || defined(UNIX_MACOS)
- return Tick() + 1;
- #else
- return TickRealtimeManual() + 1;
- #endif
- }
- #ifndef OS_WIN32
- static UINT64 last_manual_tick = 0;
- static UINT64 manual_tick_add_value = 0;
- // For systems which not have clock_gettime (such as MacOS X)
- UINT TickRealtimeManual()
- {
- UINT64 ret;
- Lock(tick_manual_lock);
- {
- ret = TickGetRealtimeTickValue64();
- if (last_manual_tick != 0 && (last_manual_tick > ret))
- {
- manual_tick_add_value += (last_manual_tick - ret);
- }
- last_manual_tick = ret;
- }
- Unlock(tick_manual_lock);
- return (UINT)(ret + manual_tick_add_value);
- }
- // Returns a appropriate value from the current time
- UINT64 TickGetRealtimeTickValue64()
- {
- struct timeval tv;
- struct timezone tz;
- UINT64 ret;
- memset(&tv, 0, sizeof(tv));
- memset(&tz, 0, sizeof(tz));
- gettimeofday(&tv, &tz);
- if (sizeof(tv.tv_sec) != 4)
- {
- ret = (UINT64)tv.tv_sec * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
- }
- else
- {
- ret = (UINT64)((UINT64)((UINT32)tv.tv_sec)) * 1000ULL + (UINT64)tv.tv_usec / 1000ULL;
- }
- return ret;
- }
- #endif // OS_WIN32
- // Get the number of CPUs
- UINT GetNumberOfCpu()
- {
- UINT ret = 0;
- if (cached_number_of_cpus == 0)
- {
- UINT i = 0;
- #ifdef OS_WIN32
- i = Win32GetNumberOfCpuInner();
- #else // OS_WIN32
- i = UnixGetNumberOfCpuInner();
- #endif // OS_WIN32
- if (i == 0)
- {
- i = 8;
- }
- cached_number_of_cpus = i;
- }
- ret = cached_number_of_cpus;
- if (ret == 0)
- {
- ret = 1;
- }
- if (ret > 128)
- {
- ret = 128;
- }
- return ret;
- }
- // Creating a thread list
- LIST *NewThreadList()
- {
- LIST *o = NewList(NULL);
- return o;
- }
- // Remove the thread from the thread list
- void DelThreadFromThreadList(LIST *o, THREAD *t)
- {
- // Validate arguments
- if (o == NULL || t == NULL)
- {
- return;
- }
- LockList(o);
- {
- if (Delete(o, t))
- {
- ReleaseThread(t);
- }
- }
- UnlockList(o);
- }
- // Add the thread to the thread list
- void AddThreadToThreadList(LIST *o, THREAD *t)
- {
- // Validate arguments
- if (o == NULL || t == NULL)
- {
- return;
- }
- LockList(o);
- {
- if (IsInList(o, t) == false)
- {
- AddRef(t->ref);
- Add(o, t);
- }
- }
- UnlockList(o);
- }
- // Maintain thread list
- void MainteThreadList(LIST *o)
- {
- UINT i;
- LIST *delete_list = NULL;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- LockList(o);
- {
- for (i = 0;i < LIST_NUM(o);i++)
- {
- THREAD *t = LIST_DATA(o, i);
- if (t->Stopped)
- {
- if (delete_list == NULL)
- {
- delete_list = NewListFast(NULL);
- }
- Add(delete_list, t);
- }
- }
- if (delete_list != NULL)
- {
- for (i = 0;i < LIST_NUM(delete_list);i++)
- {
- THREAD *t = LIST_DATA(delete_list, i);
- ReleaseThread(t);
- Delete(o, t);
- }
- ReleaseList(delete_list);
- }
- }
- UnlockList(o);
- }
- // Wait until all threads in the thread list will be stopped
- void WaitAllThreadsWillBeStopped(LIST *o)
- {
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- while (LIST_NUM(o) != 0)
- {
- SleepThread(100);
- }
- }
- // Stop all the threads in the thread list
- void StopThreadList(LIST *o)
- {
- UINT i;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- LockList(o);
- {
- for (i = 0;i < LIST_NUM(o);i++)
- {
- THREAD *t = LIST_DATA(o, i);
- WaitThread(t, INFINITE);
- }
- }
- UnlockList(o);
- }
- // Release the thread list
- void FreeThreadList(LIST *o)
- {
- UINT i;
- // Validate arguments
- if (o == NULL)
- {
- return;
- }
- LockList(o);
- {
- for (i = 0;i < LIST_NUM(o);i++)
- {
- THREAD *t = LIST_DATA(o, i);
- WaitThread(t, INFINITE);
- ReleaseThread(t);
- }
- DeleteAll(o);
- }
- UnlockList(o);
- ReleaseList(o);
- }
- // Get the home directory
- void GetHomeDirW(wchar_t *path, UINT size)
- {
- // Validate arguments
- if (path == NULL)
- {
- return;
- }
- if (GetEnvW(L"HOME", path, size) == false)
- {
- wchar_t drive[MAX_SIZE];
- wchar_t hpath[MAX_SIZE];
- if (GetEnvW(L"HOMEDRIVE", drive, sizeof(drive)) &&
- GetEnvW(L"HOMEPATH", hpath, sizeof(hpath)))
- {
- UniFormat(path, size, L"%s%s", drive, hpath);
- }
- else
- {
- #ifdef OS_WIN32
- Win32GetCurrentDirW(path, size);
- #else // OS_WIN32
- UnixGetCurrentDirW(path, size);
- #endif // OS_WIN32
- }
- }
- }
- void GetHomeDir(char *path, UINT size)
- {
- // Validate arguments
- if (path == NULL)
- {
- return;
- }
- if (GetEnv("HOME", path, size) == false)
- {
- char drive[MAX_SIZE];
- char hpath[MAX_SIZE];
- if (GetEnv("HOMEDRIVE", drive, sizeof(drive)) &&
- GetEnv("HOMEPATH", hpath, sizeof(hpath)))
- {
- Format(path, size, "%s%s", drive, hpath);
- }
- else
- {
- #ifdef OS_WIN32
- Win32GetCurrentDir(path, size);
- #else // OS_WIN32
- UnixGetCurrentDir(path, size);
- #endif // OS_WIN32
- }
- }
- }
- // Get the environment variable string
- bool GetEnv(char *name, char *data, UINT size)
- {
- char *ret;
- // Validate arguments
- if (name == NULL || data == NULL)
- {
- return false;
- }
- StrCpy(data, size, "");
- ret = getenv(name);
- if (ret == NULL)
- {
- return false;
- }
- StrCpy(data, size, ret);
- return true;
- }
- bool GetEnvW(wchar_t *name, wchar_t *data, UINT size)
- {
- #ifdef OS_WIN32
- return GetEnvW_ForWin32(name, data, size);
- #else // OS_WIN32
- return GetEnvW_ForUnix(name, data, size);
- #endif // OS_WIN32
- }
- #ifdef OS_WIN32
- bool GetEnvW_ForWin32(wchar_t *name, wchar_t *data, UINT size)
- {
- wchar_t *ret;
- // Validate arguments
- if (name == NULL || data == NULL)
- {
- return false;
- }
- if (IsNt() == false)
- {
- bool ret;
- char *name_a = CopyUniToStr(name);
- char data_a[MAX_SIZE];
- ret = GetEnv(name_a, data_a, sizeof(data_a));
- if (ret)
- {
- StrToUni(data, size, data_a);
- }
- Free(name_a);
- return ret;
- }
- UniStrCpy(data, size, L"");
- ret = _wgetenv(name);
- if (ret == NULL)
- {
- return false;
- }
- UniStrCpy(data, size, ret);
- return true;
- }
- #endif // OS_WIN32
- #ifdef OS_UNIX
- bool GetEnvW_ForUnix(wchar_t *name, wchar_t *data, UINT size)
- {
- char *name_a;
- bool ret;
- char data_a[MAX_SIZE];
- // Validate arguments
- if (name == NULL || data == NULL)
- {
- return false;
- }
- name_a = CopyUniToUtf(name);
- ret = GetEnv(name_a, data_a, sizeof(data_a));
- if (ret)
- {
- UtfToUni(data, size, data_a);
- }
- Free(name_a);
- return ret;
- }
- #endif // OS_UNIX
- // Get the memory information
- void GetMemInfo(MEMINFO *info)
- {
- OSGetMemInfo(info);
- }
- // Start the single-instance
- INSTANCE *NewSingleInstance(char *instance_name)
- {
- return NewSingleInstanceEx(instance_name, false);
- }
- INSTANCE *NewSingleInstanceEx(char *instance_name, bool user_local)
- {
- char name[MAX_SIZE];
- INSTANCE *ret;
- void *data;
- if (instance_name != NULL)
- {
- if (user_local == false)
- {
- HashInstanceName(name, sizeof(name), instance_name);
- }
- else
- {
- HashInstanceNameLocal(name, sizeof(name), instance_name);
- }
- data = OSNewSingleInstance(name);
- }
- else
- {
- data = OSNewSingleInstance(NULL);
- }
- if (data == NULL)
- {
- return NULL;
- }
- ret = ZeroMalloc(sizeof(INSTANCE));
- if (instance_name != NULL)
- {
- ret->Name = CopyStr(instance_name);
- }
- ret->pData = data;
- return ret;
- }
- // Release of single instance
- void FreeSingleInstance(INSTANCE *inst)
- {
- // Validate arguments
- if (inst == NULL)
- {
- return;
- }
- OSFreeSingleInstance(inst->pData);
- if (inst->Name != NULL)
- {
- Free(inst->Name);
- }
- Free(inst);
- }
- // Hashing the instance name
- void HashInstanceName(char *name, UINT size, char *instance_name)
- {
- char tmp[MAX_SIZE];
- UCHAR hash[SHA1_SIZE];
- char key[11];
- // Validate arguments
- if (name == NULL || instance_name == NULL)
- {
- return;
- }
- StrCpy(tmp, sizeof(tmp), instance_name);
- Trim(tmp);
- StrUpper(tmp);
- Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
- BinToStr(key, sizeof(key), hash, 5);
- key[10] = 0;
- Format(name, size, "VPN-%s", key);
- if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
- {
- if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
- GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
- {
- StrCpy(tmp, sizeof(tmp), name);
- Format(name, size, "Global\\%s", tmp);
- }
- }
- }
- void HashInstanceNameLocal(char *name, UINT size, char *instance_name)
- {
- char tmp[MAX_SIZE];
- UCHAR hash[SHA1_SIZE];
- char key[11];
- // Validate arguments
- if (name == NULL || instance_name == NULL)
- {
- return;
- }
- StrCpy(tmp, sizeof(tmp), instance_name);
- Trim(tmp);
- StrUpper(tmp);
- Hash(hash, tmp, StrLen(tmp), SHA1_SIZE);
- BinToStr(key, sizeof(key), hash, 5);
- key[10] = 0;
- Format(name, size, "VPN-%s", key);
- if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType))
- {
- if (GET_KETA(GetOsInfo()->OsType, 100) >= 2 ||
- GetOsInfo()->OsType == OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER)
- {
- StrCpy(tmp, sizeof(tmp), name);
- Format(name, size, "Local\\%s", tmp);
- }
- }
- }
- // Run the process
- bool Run(char *filename, char *arg, bool hide, bool wait)
- {
- // Validate arguments
- if (filename == NULL)
- {
- return false;
- }
- return OSRun(filename, arg, hide, wait);
- }
- bool RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
- {
- // Validate arguments
- if (filename == NULL)
- {
- return false;
- }
- return OSRunW(filename, arg, hide, wait);
- }
- // Date and time related functions
- void GetDateTimeStr64Uni(wchar_t *str, UINT size, UINT64 sec64)
- {
- char tmp[MAX_SIZE];
- if (str == NULL)
- {
- return;
- }
- GetDateTimeStr64(tmp, sizeof(tmp), sec64);
- StrToUni(str, size, tmp);
- }
- void GetDateTimeStr64(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, sec64);
- GetDateTimeStr(str, size, &st);
- }
- void GetDateTimeStrMilli64(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, sec64);
- GetDateTimeStrMilli(str, size, &st);
- }
- void GetDateTimeStrMilli64ForFileName(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, sec64);
- GetDateTimeStrMilliForFileName(str, size, &st);
- }
- void GetDateTimeStrMilliForFileName(char *str, UINT size, SYSTEMTIME *tm)
- {
- Format(str, size, "%04u%02u%02u_%02u%02u%02u",
- tm->wYear, tm->wMonth, tm->wDay, tm->wHour, tm->wMinute, tm->wSecond);
- }
- void GetDateStr64(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- if (sec64 == 0)
- {
- StrCpy(str, size, "(Unknown)");
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetDateStr(str, size, &st);
- }
- void GetDateTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
- {
- SYSTEMTIME st;
- if (locale == NULL)
- {
- locale = ¤t_locale;
- }
- if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
- {
- UniStrCpy(str, size, locale->Unknown);
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetDateTimeStrEx(str, size, &st, locale);
- }
- void GetTimeStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
- {
- SYSTEMTIME st;
- if (locale == NULL)
- {
- locale = ¤t_locale;
- }
- if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
- {
- UniStrCpy(str, size, locale->Unknown);
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetTimeStrEx(str, size, &st, locale);
- }
- void GetDateStrEx64(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
- {
- SYSTEMTIME st;
- if (locale == NULL)
- {
- locale = ¤t_locale;
- }
- if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
- {
- UniStrCpy(str, size, locale->Unknown);
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetDateStrEx(str, size, &st, locale);
- }
- void GetTimeStrMilli64(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
- {
- StrCpy(str, size, "(Unknown)");
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetTimeStrMilli(str, size, &st);
- }
- void GetTimeStr64(char *str, UINT size, UINT64 sec64)
- {
- SYSTEMTIME st;
- if (sec64 == 0 || SystemToLocal64(sec64) == 0 || LocalToSystem64(sec64) == 0)
- {
- StrCpy(str, size, "(Unknown)");
- return;
- }
- UINT64ToSystem(&st, sec64);
- GetTimeStr(str, size, &st);
- }
- // Convert to a time to be used safely in the current POSIX implementation
- UINT64 SafeTime64(UINT64 sec64)
- {
- return MAKESURE(sec64, 0, 4102243323123ULL);
- }
- // Thread pool
- static SK *thread_pool = NULL;
- static COUNTER *thread_count = NULL;
- // Initialization of thread pool
- void InitThreading()
- {
- thread_pool = NewSk();
- thread_count = NewCounter();
- }
- // Release of thread pool
- void FreeThreading()
- {
- while (true)
- {
- if (Count(thread_count) == 0)
- {
- break;
- }
- SleepThread(25);
- }
- while (true)
- {
- THREAD_POOL_DATA *pd;
- THREAD *t = Pop(thread_pool);
- if (t == NULL)
- {
- break;
- }
- pd = (THREAD_POOL_DATA *)t->param;
- pd->ThreadProc = NULL;
- Set(pd->Event);
- WaitThreadInternal(t);
- pd = (THREAD_POOL_DATA *)t->param;
- ReleaseEvent(pd->Event);
- ReleaseEvent(pd->InitFinishEvent);
- ReleaseThreadInternal(t);
- Free(pd);
- }
- ReleaseSk(thread_pool);
- DeleteCounter(thread_count);
- thread_count = NULL;
- }
- // Thread pool procedure
- void ThreadPoolProc(THREAD *t, void *param)
- {
- THREAD_POOL_DATA *pd;
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- pd = (THREAD_POOL_DATA *)param;
- NoticeThreadInitInternal(t);
- while (true)
- {
- THREAD *thread;
- UINT i, num;
- EVENT **ee;
- // Wait for the next job
- Wait(pd->Event, INFINITE);
- if (pd->ThreadProc == NULL)
- {
- // Stop the pool thread
- break;
- }
- thread = pd->Thread;
- thread->ThreadId = ThreadId();
- // Initialization is completed
- Set(pd->InitFinishEvent);
- // Set the thread name
- if (thread->Name != NULL)
- {
- SetThreadName(thread->ThreadId, thread->Name, thread->param);
- }
- else
- {
- SetThreadName(thread->ThreadId, "Unknown", 0);
- }
- // Run the thread procedure
- pd->ThreadProc(pd->Thread, thread->param);
- // Set the thread name
- SetThreadName(thread->ThreadId, NULL, 0);
- pd->Thread->Stopped = true;
- thread->PoolHalting = true;
- // Set the waiting event list
- LockList(thread->PoolWaitList);
- {
- num = LIST_NUM(thread->PoolWaitList);
- ee = ToArray(thread->PoolWaitList);
- DeleteAll(thread->PoolWaitList);
- }
- UnlockList(thread->PoolWaitList);
- for (i = 0;i < num;i++)
- {
- EVENT *e = ee[i];
- Set(e);
- ReleaseEvent(e);
- }
- Free(ee);
- while (true)
- {
- if (Count(thread->ref->c) <= 1)
- {
- break;
- }
- Wait(thread->release_event, 256);
- }
- ReleaseThread(thread);
- #ifdef OS_WIN32
- // For Win32: Recover the priority of the thread
- MsRestoreThreadPriority();
- #endif // OS_WIN32
- // Register the thread itself to the thread pool
- LockSk(thread_pool);
- {
- Push(thread_pool, t);
- }
- UnlockSk(thread_pool);
- Dec(thread_count);
- }
- }
- // Set the thread name
- void SetThreadName(UINT thread_id, char *name, void *param)
- {
- #ifdef OS_WIN32
- if (IsDebug())
- {
- char tmp[MAX_SIZE];
- if (name == NULL)
- {
- strcpy(tmp, "idle");
- }
- else
- {
- sprintf(tmp, "%s (0x%x)", name, (UINT)param);
- }
- Win32SetThreadName(thread_id, tmp);
- }
- #else // OS_WIN32
- #ifdef _DEBUG
- #ifdef PR_SET_NAME
- char tmp[MAX_SIZE];
- if (name == NULL)
- {
- strcpy(tmp, "idle");
- }
- else
- {
- sprintf(tmp, "%s (%p)", name, param);
- }
- tmp[15] = 0;
- prctl(PR_SET_NAME, (unsigned long)tmp, 0, 0, 0);
- #endif // PR_SET_NAME
- #endif // _DEBUG
- #endif // OS_WIN32
- }
- // Do Nothing
- UINT DoNothing()
- {
- return g_zero;
- }
- // Thread creation (pool)
- THREAD *NewThreadNamed(THREAD_PROC *thread_proc, void *param, char *name)
- {
- THREAD *host = NULL;
- THREAD_POOL_DATA *pd = NULL;
- THREAD *ret;
- bool new_thread = false;
- // Validate arguments
- if (thread_proc == NULL)
- {
- return NULL;
- }
- if (IsTrackingEnabled() == false)
- {
- DoNothing();
- }
- Inc(thread_count);
- LockSk(thread_pool);
- {
- // Examine whether there is a thread that is currently vacant in the pool
- host = Pop(thread_pool);
- }
- UnlockSk(thread_pool);
- if (host == NULL)
- {
- // Create a new thread because a vacant thread is not found
- pd = ZeroMalloc(sizeof(THREAD_POOL_DATA));
- pd->Event = NewEvent();
- pd->InitFinishEvent = NewEvent();
- host = NewThreadInternal(ThreadPoolProc, pd);
- WaitThreadInitInternal(host);
- new_thread = true;
- }
- else
- {
- pd = (THREAD_POOL_DATA *)host->param;
- }
- // Creating a thread pool
- ret = ZeroMalloc(sizeof(THREAD));
- ret->ref = NewRef();
- ret->thread_proc = thread_proc;
- ret->param = param;
- ret->pData = NULL;
- ret->init_finished_event = NewEvent();
- ret->PoolThread = true;
- ret->PoolWaitList = NewList(NULL);
- ret->PoolHostThread = host;
- ret->release_event = NewEvent();
- if (IsEmptyStr(name) == false)
- {
- ret->Name = CopyStr(name);
- }
- // Run
- pd->ThreadProc = thread_proc;
- pd->Thread = ret;
- AddRef(ret->ref);
- Set(pd->Event);
- Wait(pd->InitFinishEvent, INFINITE);
- current_num_thread++;
- // Debug("current_num_thread = %u\n", current_num_thread);
- return ret;
- }
- // Clean up of thread (pool)
- void CleanupThread(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- ReleaseEvent(t->init_finished_event);
- ReleaseEvent(t->release_event);
- ReleaseList(t->PoolWaitList);
- if (t->Name != NULL)
- {
- Free(t->Name);
- }
- Free(t);
- current_num_thread--;
- //Debug("current_num_thread = %u\n", current_num_thread);
- }
- // Release thread (pool)
- void ReleaseThread(THREAD *t)
- {
- UINT ret;
- EVENT *e;
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- e = t->release_event;
- if (e != NULL)
- {
- AddRef(e->ref);
- }
- ret = Release(t->ref);
- Set(e);
- ReleaseEvent(e);
- if (ret == 0)
- {
- CleanupThread(t);
- }
- }
- // Notify the completion of the thread initialization (pool)
- void NoticeThreadInit(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- // Notification
- Set(t->init_finished_event);
- }
- // Wait the completion of the thread initialization (pool)
- void WaitThreadInit(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- // KS
- KS_INC(KS_WAITFORTHREAD_COUNT);
- // Wait
- Wait(t->init_finished_event, INFINITE);
- }
- // Wait for the termination of the thread (pool)
- bool WaitThread(THREAD *t, UINT timeout)
- {
- bool ret = false;
- EVENT *e = NULL;
- // Validate arguments
- if (t == NULL)
- {
- return false;
- }
- LockList(t->PoolWaitList);
- {
- if (t->PoolHalting)
- {
- // Has already been stopped
- ret = true;
- }
- else
- {
- // Register the completion notifying event to the list
- e = NewEvent();
- AddRef(e->ref);
- Insert(t->PoolWaitList, e);
- }
- }
- UnlockList(t->PoolWaitList);
- if (e != NULL)
- {
- // Wait Event
- ret = Wait(e, timeout);
- LockList(t->PoolWaitList);
- {
- if (Delete(t->PoolWaitList, e))
- {
- ReleaseEvent(e);
- }
- }
- UnlockList(t->PoolWaitList);
- ReleaseEvent(e);
- }
- return ret;
- }
- // Get Thread ID
- UINT ThreadId()
- {
- return OSThreadId();
- }
- // Creating a thread
- THREAD *NewThreadInternal(THREAD_PROC *thread_proc, void *param)
- {
- THREAD *t;
- UINT retry = 0;
- // Validate arguments
- if (thread_proc == NULL)
- {
- return NULL;
- }
- // Initialize Thread object
- t = ZeroMalloc(sizeof(THREAD));
- t->init_finished_event = NewEvent();
- t->param = param;
- t->ref = NewRef();
- t->thread_proc = thread_proc;
- // Wait until the OS to initialize the thread
- while (true)
- {
- if ((retry++) > 60)
- {
- printf("\n\n*** error: new thread create failed.\n\n");
- AbortExit();
- }
- if (OSInitThread(t))
- {
- break;
- }
- SleepThread(500);
- }
- // KS
- KS_INC(KS_NEWTHREAD_COUNT);
- return t;
- }
- // Release of thread
- void ReleaseThreadInternal(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- if (Release(t->ref) == 0)
- {
- CleanupThreadInternal(t);
- }
- }
- // Clean up of the thread
- void CleanupThreadInternal(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- // Release of the thread
- OSFreeThread(t);
- // Release the event
- ReleaseEvent(t->init_finished_event);
- // Memory release
- Free(t);
- // KS
- KS_INC(KS_FREETHREAD_COUNT);
- }
- // Wait for the termination of the thread
- bool WaitThreadInternal(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return false;
- }
- return OSWaitThread(t);
- }
- // Notify that the thread initialization is complete
- void NoticeThreadInitInternal(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- // Notify
- Set(t->init_finished_event);
- }
- // Wait for completion of thread initialization
- void WaitThreadInitInternal(THREAD *t)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- // KS
- KS_INC(KS_WAITFORTHREAD_COUNT);
- // Wait
- Wait(t->init_finished_event, INFINITE);
- }
- // Get the date and time string by using the locale information
- void GetDateTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
- {
- wchar_t tmp1[MAX_SIZE];
- wchar_t tmp2[MAX_SIZE];
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- GetDateStrEx(tmp1, sizeof(tmp1), st, locale);
- GetTimeStrEx(tmp2, sizeof(tmp2), st, locale);
- UniFormat(str, size, L"%s %s", tmp1, tmp2);
- }
- // Get the time string by using the locale information
- void GetTimeStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
- {
- wchar_t *tag = L"%02u%s%02u%s%02u%s";
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
- {
- tag = L"%2u%s%2u%s%2u%s";
- }
- locale = (locale != NULL ? locale : ¤t_locale);
- UniFormat(str, size,
- tag,
- st->wHour, locale->HourStr,
- st->wMinute, locale->MinuteStr,
- st->wSecond, locale->SecondStr);
- }
- // Get a date string by using the locale information
- void GetDateStrEx(wchar_t *str, UINT size, SYSTEMTIME *st, LOCALE *locale)
- {
- wchar_t *tag = L"%04u%s%02u%s%02u%s (%s)";
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- if (_GETLANG() == SE_LANG_JAPANESE || _GETLANG() == SE_LANG_CHINESE_ZH)
- {
- tag = L"%4u%s%2u%s%2u%s(%s)";
- }
- locale = (locale != NULL ? locale : ¤t_locale);
- UniFormat(str, size,
- tag,
- st->wYear, locale->YearStr,
- st->wMonth, locale->MonthStr,
- st->wDay, locale->DayStr,
- locale->DayOfWeek[st->wDayOfWeek]);
- }
- // Get the time string to milliseconds (for example, 12:34:56.789)
- void GetTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
- {
- // Validate arguments
- if (st == NULL || str == NULL)
- {
- return;
- }
- Format(str, size, "%02u:%02u:%02u.%03u",
- st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
- }
- // Get the time string (for example, 12:34:56)
- void GetTimeStr(char *str, UINT size, SYSTEMTIME *st)
- {
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- Format(str, size, "%02u:%02u:%02u",
- st->wHour, st->wMinute, st->wSecond);
- }
- // Get the date string (example: 2004/07/23)
- void GetDateStr(char *str, UINT size, SYSTEMTIME *st)
- {
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- Format(str, size, "%04u-%02u-%02u",
- st->wYear, st->wMonth, st->wDay);
- }
- // Get the date and time string (example: 2004/07/23 12:34:56)
- void GetDateTimeStr(char *str, UINT size, SYSTEMTIME *st)
- {
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u",
- st->wYear, st->wMonth, st->wDay,
- st->wHour, st->wMinute, st->wSecond);
- }
- // Get the date and time string in milliseconds (example: 2004/07/23 12:34:56.789)
- void GetDateTimeStrMilli(char *str, UINT size, SYSTEMTIME *st)
- {
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- return;
- }
- Format(str, size, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
- st->wYear, st->wMonth, st->wDay,
- st->wHour, st->wMinute, st->wSecond,
- st->wMilliseconds);
- }
- // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to UINT64
- UINT64 DateTimeStrRFC3339ToSystemTime64(char *str)
- {
- SYSTEMTIME st;
- if (DateTimeStrRFC3339ToSystemTime(&st, str))
- {
- return SystemToUINT64(&st);
- }
- else
- {
- return 0;
- }
- }
- // Convert string RFC3339 format (example: 2017-09-27T18:25:55.434-9:00) to SYSTEMTIME
- bool DateTimeStrRFC3339ToSystemTime(SYSTEMTIME *st, char *str)
- {
- bool ok = false;
- UINT index_plus;
- char tmp[MAX_PATH];
- Zero(st, sizeof(SYSTEMTIME));
- if (st == NULL || str == NULL)
- {
- return false;
- }
- StrCpy(tmp, sizeof(tmp), str);
- index_plus = SearchStrEx(tmp, "+", 0, false);
- if (index_plus != INFINITE)
- {
- tmp[index_plus] = 0;
- }
- if (StrLen(tmp) >= 19)
- {
- if (tmp[4] == '-' && tmp[7] == '-' && tmp[10] == 'T' && tmp[13] == ':' &&
- tmp[16] == ':')
- {
- char str_year[16], str_month[16], str_day[16], str_hour[16], str_minute[16],
- str_second[16], str_msec[16];
- StrCpy(str_year, sizeof(str_year), tmp + 0);
- str_year[4] = 0;
- StrCpy(str_month, sizeof(str_month), tmp + 5);
- str_month[2] = 0;
- StrCpy(str_day, sizeof(str_day), tmp + 8);
- str_day[2] = 0;
- StrCpy(str_hour, sizeof(str_hour), tmp + 11);
- str_hour[2] = 0;
- StrCpy(str_minute, sizeof(str_minute), tmp + 14);
- str_minute[2] = 0;
- StrCpy(str_second, sizeof(str_second), tmp + 17);
- str_second[2] = 0;
- str_msec[0] = 0;
- if (StrLen(tmp) >= 21 && tmp[19] == '.')
- {
- StrCpy(str_msec, sizeof(str_msec), tmp + 20);
- str_msec[StrLen(tmp) - 21] = 0;
- while (StrLen(str_msec) < 3)
- {
- StrCat(str_msec, sizeof(str_msec), "0");
- }
- str_msec[3] = 0;
- }
- st->wYear = ToInt(str_year);
- st->wMonth = ToInt(str_month);
- st->wDay = ToInt(str_day);
- st->wHour = ToInt(str_hour);
- st->wMinute = ToInt(str_minute);
- st->wSecond = ToInt(str_second);
- st->wMilliseconds = ToInt(str_msec);
- NormalizeSystem(st);
- ok = true;
- }
- }
- return ok;
- }
- // Get the date and time string in RFC3339 format (example: 2017-09-27T18:25:55.434-9:00)
- void GetDateTimeStrRFC3339(char *str, UINT size, SYSTEMTIME *st, int timezone_min){
- // Validate arguments
- if (str == NULL || st == NULL)
- {
- ClearStr(str, size);
- return;
- }
- if(timezone_min == 0){
- Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03uZ",
- st->wYear, st->wMonth, st->wDay,
- st->wHour, st->wMinute, st->wSecond,
- st->wMilliseconds);
- }else{
- Format(str, size, "%04u-%02u-%02uT%02u:%02u:%02u.%03u%+02d:%02d",
- st->wYear, st->wMonth, st->wDay,
- st->wHour, st->wMinute, st->wSecond,
- st->wMilliseconds, timezone_min/60, timezone_min%60);
- }
- }
- // Get the time string
- void GetSpanStr(char *str, UINT size, UINT64 sec64)
- {
- char tmp[MAX_SIZE];
- // Validate arguments
- if (str == NULL)
- {
- return;
- }
- StrCpy(tmp, sizeof(tmp), "");
- if (sec64 >= (UINT64)(1000 * 3600 * 24))
- {
- Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
- }
- Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u", tmp,
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
- (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000);
- Trim(tmp);
- StrCpy(str, size, tmp);
- }
- // Get the time string (in milliseconds)
- void GetSpanStrMilli(char *str, UINT size, UINT64 sec64)
- {
- char tmp[MAX_SIZE];
- // Validate arguments
- if (str == NULL)
- {
- return;
- }
- StrCpy(tmp, sizeof(tmp), "");
- if (sec64 >= (UINT64)(1000 * 3600 * 24))
- {
- Format(tmp, sizeof(tmp), "%u:", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)));
- }
- Format(tmp, sizeof(tmp), "%s%02u:%02u:%02u.%03u", tmp,
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
- (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
- (UINT)(sec64 % (UINT64)(1000)));
- Trim(tmp);
- StrCpy(str, size, tmp);
- }
- // Get the time string (extended)
- void GetSpanStrEx(wchar_t *str, UINT size, UINT64 sec64, LOCALE *locale)
- {
- wchar_t tmp[MAX_SIZE];
- // Validate arguments
- if (str == NULL)
- {
- return;
- }
- locale = (locale != NULL ? locale : ¤t_locale);
- UniStrCpy(tmp, sizeof(tmp), L"");
- if (sec64 >= (UINT64)(1000 * 3600 * 24))
- {
- UniFormat(tmp, sizeof(tmp), L"%u%s ", (UINT)(sec64 / (UINT64)(1000 * 3600 * 24)),
- locale->SpanDay);
- }
- UniFormat(tmp, sizeof(tmp), L"%s%u%s %02u%s %02u%s", tmp,
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60 * 24)) / (1000 * 60 * 60),
- locale->SpanHour,
- (UINT)(sec64 % (UINT64)(1000 * 60 * 60)) / (1000 * 60),
- locale->SpanMinute,
- (UINT)(sec64 % (UINT64)(1000 * 60)) / 1000,
- locale->SpanSecond);
- UniTrim(tmp);
- UniStrCpy(str, size, tmp);
- }
- // Get the current locale information
- void GetCurrentLocale(LOCALE *locale)
- {
- // Validate arguments
- if (locale == NULL)
- {
- return;
- }
- Copy(locale, ¤t_locale, sizeof(LOCALE));
- }
- // Set the locale information
- void SetLocale(wchar_t *str)
- {
- wchar_t *set_locale_str;
- LOCALE tmp;
- if (str != NULL)
- {
- set_locale_str = str;
- }
- else
- {
- set_locale_str = default_locale_str;
- }
- if (LoadLocale(&tmp, set_locale_str) == false)
- {
- if (LoadLocale(&tmp, default_locale_str) == false)
- {
- return;
- }
- }
- Copy(¤t_locale, &tmp, sizeof(LOCALE));
- }
- #define COPY_LOCALE_STR(dest, size, src) UniStrCpy(dest, size, UniStrCmp(src, L"$") == 0 ? L"" : src)
- // Read the locale information
- bool LoadLocale(LOCALE *locale, wchar_t *str)
- {
- UNI_TOKEN_LIST *tokens;
- UINT i;
- // Validate arguments
- if (locale == NULL || str == NULL)
- {
- return false;
- }
- // Analysis of the token
- tokens = UniParseToken(str, L" ");
- if (tokens->NumTokens != 18)
- {
- UniFreeToken(tokens);
- return false;
- }
- // Set to the structure
- Zero(locale, sizeof(LOCALE));
- COPY_LOCALE_STR(locale->YearStr, sizeof(locale->YearStr), tokens->Token[0]);
- COPY_LOCALE_STR(locale->MonthStr, sizeof(locale->MonthStr), tokens->Token[1]);
- COPY_LOCALE_STR(locale->DayStr, sizeof(locale->DayStr), tokens->Token[2]);
- COPY_LOCALE_STR(locale->HourStr, sizeof(locale->HourStr), tokens->Token[3]);
- COPY_LOCALE_STR(locale->MinuteStr, sizeof(locale->MinuteStr), tokens->Token[4]);
- COPY_LOCALE_STR(locale->SecondStr, sizeof(locale->SecondStr), tokens->Token[5]);
- for (i = 0;i < 7;i++)
- {
- COPY_LOCALE_STR(locale->DayOfWeek[i], sizeof(locale->DayOfWeek[i]),
- tokens->Token[6 + i]);
- }
- COPY_LOCALE_STR(locale->SpanDay, sizeof(locale->SpanDay), tokens->Token[13]);
- COPY_LOCALE_STR(locale->SpanHour, sizeof(locale->SpanHour), tokens->Token[14]);
- COPY_LOCALE_STR(locale->SpanMinute, sizeof(locale->SpanMinute), tokens->Token[15]);
- COPY_LOCALE_STR(locale->SpanSecond, sizeof(locale->SpanSecond), tokens->Token[16]);
- COPY_LOCALE_STR(locale->Unknown, sizeof(locale->Unknown), tokens->Token[17]);
- UniFreeToken(tokens);
- return true;
- }
- // Convert SYSTEMTIME into DOS date
- USHORT SystemToDosDate(SYSTEMTIME *st)
- {
- return (USHORT)(
- ((UINT)(st->wYear - 1980) << 9) |
- ((UINT)st->wMonth<< 5) |
- (UINT)st->wDay);
- }
- USHORT System64ToDosDate(UINT64 i)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, i);
- return SystemToDosDate(&st);
- }
- // Convert SYSTEMTIME into DOS time
- USHORT SystemToDosTime(SYSTEMTIME *st)
- {
- return (USHORT)(
- ((UINT)st->wHour << 11) |
- ((UINT)st->wMinute << 5) |
- ((UINT)st->wSecond >> 1));
- }
- USHORT System64ToDosTime(UINT64 i)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, i);
- return SystemToDosTime(&st);
- }
- // Convert the tm to the SYSTEMTIME
- void TmToSystem(SYSTEMTIME *st, struct tm *t)
- {
- struct tm tmp;
- // Validate arguments
- if (st == NULL || t == NULL)
- {
- return;
- }
- Copy(&tmp, t, sizeof(struct tm));
- NormalizeTm(&tmp);
- Zero(st, sizeof(SYSTEMTIME));
- st->wYear = MAKESURE(tmp.tm_year + 1900, 1970, 2099);
- st->wMonth = MAKESURE(tmp.tm_mon + 1, 1, 12);
- st->wDay = MAKESURE(tmp.tm_mday, 1, 31);
- st->wDayOfWeek = MAKESURE(tmp.tm_wday, 0, 6);
- st->wHour = MAKESURE(tmp.tm_hour, 0, 23);
- st->wMinute = MAKESURE(tmp.tm_min, 0, 59);
- st->wSecond = MAKESURE(tmp.tm_sec, 0, 59);
- st->wMilliseconds = 0;
- }
- // Convert the SYSTEMTIME to tm
- void SystemToTm(struct tm *t, SYSTEMTIME *st)
- {
- // Validate arguments
- if (t == NULL || st == NULL)
- {
- return;
- }
- Zero(t, sizeof(struct tm));
- t->tm_year = MAKESURE(st->wYear, 1970, 2099) - 1900;
- t->tm_mon = MAKESURE(st->wMonth, 1, 12) - 1;
- t->tm_mday = MAKESURE(st->wDay, 1, 31);
- t->tm_hour = MAKESURE(st->wHour, 0, 23);
- t->tm_min = MAKESURE(st->wMinute, 0, 59);
- t->tm_sec = MAKESURE(st->wSecond, 0, 59);
- t->tm_isdst = -1;
- NormalizeTm(t);
- }
- // Convert the time_t to SYSTEMTIME
- void TimeToSystem(SYSTEMTIME *st, time_64t t)
- {
- struct tm tmp;
- // Validate arguments
- if (st == NULL)
- {
- return;
- }
- TimeToTm(&tmp, t);
- TmToSystem(st, &tmp);
- }
- // Convert the time_t to 64-bit SYSTEMTIME
- UINT64 TimeToSystem64(time_64t t)
- {
- SYSTEMTIME st;
- TimeToSystem(&st, t);
- return SystemToUINT64(&st);
- }
- // Convert the SYSTEMTIME to time_t
- time_64t SystemToTime(SYSTEMTIME *st)
- {
- struct tm t;
- // Validate arguments
- if (st == NULL)
- {
- return 0;
- }
- SystemToTm(&t, st);
- return TmToTime(&t);
- }
- // Convert a 64-bit SYSTEMTIME to a time_t
- time_64t System64ToTime(UINT64 i)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, i);
- return SystemToTime(&st);
- }
- // Convert the tm to time_t
- time_64t TmToTime(struct tm *t)
- {
- time_64t tmp;
- // Validate arguments
- if (t == NULL)
- {
- return 0;
- }
- tmp = c_mkgmtime(t);
- if (tmp == (time_64t)-1)
- {
- return 0;
- }
- return tmp;
- }
- // Convert time_t to tm
- void TimeToTm(struct tm *t, time_64t time)
- {
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- Zero(t, sizeof(struct tm));
- c_gmtime_r(&time, t);
- }
- // Normalize the tm
- void NormalizeTm(struct tm *t)
- {
- time_64t tmp;
- // Validate arguments
- if (t == NULL)
- {
- return;
- }
- tmp = c_mkgmtime(t);
- if (tmp == (time_64t)-1)
- {
- return;
- }
- c_gmtime_r(&tmp, t);
- }
- // Normalize the SYSTEMTIME
- void NormalizeSystem(SYSTEMTIME *st)
- {
- UINT64 sec64;
- // Validate arguments
- if (st == NULL)
- {
- return;
- }
- sec64 = SystemToUINT64(st);
- UINT64ToSystem(st, sec64);
- }
- // Convert a 64-bit local time to a system time
- UINT64 LocalToSystem64(UINT64 t)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, t);
- LocalToSystem(&st, &st);
- return SystemToUINT64(&st);
- }
- // Convert the 64bit system time to local time
- UINT64 SystemToLocal64(UINT64 t)
- {
- SYSTEMTIME st;
- UINT64ToSystem(&st, t);
- SystemToLocal(&st, &st);
- return SystemToUINT64(&st);
- }
- // Convert local time to system time
- void LocalToSystem(SYSTEMTIME *system, SYSTEMTIME *local)
- {
- UINT64 sec64;
- // Validate arguments
- if (local == NULL || system == NULL)
- {
- return;
- }
- sec64 = (UINT64)((INT64)SystemToUINT64(local) - GetTimeDiffEx(local, true));
- UINT64ToSystem(system, sec64);
- }
- // Convert the system time to local time
- void SystemToLocal(SYSTEMTIME *local, SYSTEMTIME *system)
- {
- UINT64 sec64;
- // Validate arguments
- if (local == NULL || system == NULL)
- {
- return;
- }
- sec64 = (UINT64)((INT64)SystemToUINT64(system) + GetTimeDiffEx(system, false));
- UINT64ToSystem(local, sec64);
- }
- // Get the time difference between the local time and the system time based on the specified time
- INT64 GetTimeDiffEx(SYSTEMTIME *basetime, bool local_time)
- {
- time_t tmp;
- struct tm t1, t2;
- SYSTEMTIME snow;
- struct tm now;
- SYSTEMTIME s1, s2;
- INT64 ret;
- Copy(&snow, basetime, sizeof(SYSTEMTIME));
- if (sizeof(time_t) == 4)
- {
- if (snow.wYear >= 2038)
- {
- // For old systems: avoid the 2038-year problem
- snow.wYear = 2037;
- }
- }
- SystemToTm(&now, &snow);
- if (local_time == false)
- {
- tmp = (time_t)c_mkgmtime(&now);
- }
- else
- {
- tmp = mktime(&now);
- }
- if (tmp == (time_t)-1)
- {
- return 0;
- }
- #ifndef OS_UNIX
- Copy(&t1, localtime(&tmp), sizeof(struct tm));
- Copy(&t2, gmtime(&tmp), sizeof(struct tm));
- #else // OS_UNIX
- localtime_r(&tmp, &t1);
- gmtime_r(&tmp, &t2);
- #endif // OS_UNIX
- TmToSystem(&s1, &t1);
- TmToSystem(&s2, &t2);
- ret = (INT)SystemToUINT64(&s1) - (INT)SystemToUINT64(&s2);
- return ret;
- }
- // Convert UINT64 to the SYSTEMTIME
- void UINT64ToSystem(SYSTEMTIME *st, UINT64 sec64)
- {
- UINT64 tmp64;
- UINT sec, millisec;
- time_64t time;
- // Validate arguments
- if (st == NULL)
- {
- return;
- }
- sec64 = SafeTime64(sec64 + 32400000ULL);
- tmp64 = sec64 / (UINT64)1000;
- millisec = (UINT)(sec64 - tmp64 * (UINT64)1000);
- sec = (UINT)tmp64;
- time = (time_64t)sec;
- TimeToSystem(st, time);
- st->wMilliseconds = (WORD)millisec;
- }
- // Convert the SYSTEMTIME to UINT64
- UINT64 SystemToUINT64(SYSTEMTIME *st)
- {
- UINT64 sec64;
- time_64t time;
- // Validate arguments
- if (st == NULL)
- {
- return 0;
- }
- time = SystemToTime(st);
- //For times before 1970-01-01, clamp to the minimum
- //because we have to return an unsigned integer.
- //This is less wrong than casting it to UINT64
- //and returning a time far in the future.
- //For some reason we subtract 9 hours below, so
- //account for that here.
- if( time < 32400000LL ) return 0;
- sec64 = (UINT64)time * (UINT64)1000;
- sec64 += st->wMilliseconds;
- return sec64 - 32400000ULL;
- }
- // Get local time in UINT64
- UINT64 LocalTime64()
- {
- SYSTEMTIME s;
- LocalTime(&s);
- return SystemToUINT64(&s);
- }
- // Get the system time in UINT64
- UINT64 SystemTime64()
- {
- SYSTEMTIME s;
- SystemTime(&s);
- return SystemToUINT64(&s);
- }
- // Get local time
- void LocalTime(SYSTEMTIME *st)
- {
- SYSTEMTIME tmp;
- // Validate arguments
- if (st == NULL)
- {
- return;
- }
- SystemTime(&tmp);
- SystemToLocal(st, &tmp);
- }
- // Get the System Time
- void SystemTime(SYSTEMTIME *st)
- {
- // Validate arguments
- if (st == NULL)
- {
- return;
- }
- OSGetSystemTime(st);
- // KS
- KS_INC(KS_GETTIME_COUNT);
- }
- time_64t c_mkgmtime(struct tm *tm)
- {
- int years, months, days, hours, minutes, seconds;
- years = tm->tm_year + 1900; /* year - 1900 -> year */
- months = tm->tm_mon; /* 0..11 */
- days = tm->tm_mday - 1; /* 1..31 -> 0..30 */
- hours = tm->tm_hour; /* 0..23 */
- minutes = tm->tm_min; /* 0..59 */
- seconds = tm->tm_sec; /* 0..61 in ANSI C. */
- ADJUST_TM(seconds, minutes, 60);
- ADJUST_TM(minutes, hours, 60);
- ADJUST_TM(hours, days, 24);
- ADJUST_TM(months, years, 12);
- if (days < 0)
- do {
- if (--months < 0) {
- --years;
- months = 11;
- }
- days += monthlen(months, years);
- } while (days < 0);
- else
- while (days >= monthlen(months, years)) {
- days -= monthlen(months, years);
- if (++months >= 12) {
- ++years;
- months = 0;
- }
- }
- /* Restore adjusted values in tm structure */
- tm->tm_year = years - 1900;
- tm->tm_mon = months;
- tm->tm_mday = days + 1;
- tm->tm_hour = hours;
- tm->tm_min = minutes;
- tm->tm_sec = seconds;
- /* Set `days' to the number of days into the year. */
- days += ydays[months] + (months > 1 && leap (years));
- tm->tm_yday = days;
- /* Now calculate `days' to the number of days since Jan 1, 1970. */
- days = (unsigned)days + 365 * (unsigned)(years - 1970) +
- (unsigned)(nleap (years));
- tm->tm_wday = ((unsigned)days + 4) % 7; /* Jan 1, 1970 was Thursday. */
- tm->tm_isdst = 0;
- if (years < 1970)
- return (time_64t)-1;
- #if (defined(TM_YEAR_MAX) && defined(TM_MON_MAX) && defined(TM_MDAY_MAX))
- #if (defined(TM_HOUR_MAX) && defined(TM_MIN_MAX) && defined(TM_SEC_MAX))
- if (years > TM_YEAR_MAX ||
- (years == TM_YEAR_MAX &&
- (tm->tm_yday > ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
- (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) ||
- (tm->tm_yday == ydays[TM_MON_MAX] + (TM_MDAY_MAX - 1) +
- (TM_MON_MAX > 1 && leap (TM_YEAR_MAX)) &&
- (hours > TM_HOUR_MAX ||
- (hours == TM_HOUR_MAX &&
- (minutes > TM_MIN_MAX ||
- (minutes == TM_MIN_MAX && seconds > TM_SEC_MAX) )))))))
- return (time_64t)-1;
- #endif
- #endif
- return (time_64t)(86400L * (unsigned long)(unsigned)days +
- 3600L * (unsigned long)hours +
- (unsigned long)(60 * minutes + seconds));
- }
- // Get the system timer
- UINT Tick()
- {
- // KS
- KS_INC(KS_GETTICK_COUNT);
- return OSGetTick();
- }
- // Sleep thread
- void SleepThread(UINT time)
- {
- // KS
- KS_INC(KS_SLEEPTHREAD_COUNT);
- OSSleep(time);
- }
- // Yield
- void YieldCpu()
- {
- OSYield();
- }
- // Stop system (abnormal termination)
- void AbortExit()
- {
- #ifdef OS_WIN32
- _exit(1);
- #else // OS_WIN32
- #ifdef RLIMIT_CORE
- UnixSetResourceLimit(RLIMIT_CORE, 0);
- #endif // RLIMIT_CORE
- abort();
- #endif // OS_WIN32
- }
- void AbortExitEx(char *msg)
- {
- FILE *f;
- // Validate arguments
- if (msg == NULL)
- {
- msg = "Unknown Error";
- }
- f = fopen("abort_error_log.txt", "a");
- if (f != NULL)
- {
- SYSTEMTIME time = CLEAN;
- char time_str[128] = CLEAN;
- char* crlf = "\r\n";
- char* tag = "---------";
- LocalTime(&time);
- sprintf(time_str, "%04u-%02u-%02u %02u:%02u:%02u",
- time.wYear, time.wMonth, time.wDay,
- time.wHour, time.wMinute, time.wSecond);
- fwrite(tag, 1, strlen(tag), f);
- fwrite(crlf, 1, strlen(crlf), f);
- fwrite(time_str, 1, strlen(time_str), f);
- fwrite(crlf, 1, strlen(crlf), f);
- fwrite(msg, 1, strlen(msg), f);
- fwrite(crlf, 1, strlen(crlf), f);
- fwrite(crlf, 1, strlen(crlf), f);
- fclose(f);
- }
- fputs("Fatal Error: ", stdout);
- fputs(msg, stdout);
- fputs("\r\n", stdout);
- #ifdef OS_WIN32
- _exit(1);
- #else // OS_WIN32
- #ifdef RLIMIT_CORE
- UnixSetResourceLimit(RLIMIT_CORE, 0);
- #endif // RLIMIT_CORE
- abort();
- #endif // OS_WIN32
- }
|