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 <zlib/zlib.h>
\r
89 #include <Mayaqua/Mayaqua.h>
\r
91 #define MEMORY_SLEEP_TIME 150
\r
92 #define MEMORY_MAX_RETRY 30
\r
93 #define INIT_BUF_SIZE 10240
\r
95 #define FIFO_INIT_MEM_SIZE 4096
\r
96 #define FIFO_REALLOC_MEM_SIZE (65536 * 10) // 絶妙な値
\r
97 #define FIFO_REALLOC_MEM_SIZE_SMALL 65536
\r
99 #define INIT_NUM_RESERVED 32
\r
100 static UINT fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
\r
103 UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size)
\r
107 if (data == NULL || key == NULL || key_size == 0 || data_size == 0 ||
\r
108 (data_start >= data_size) || (data_start + key_size > data_size))
\r
113 for (i = data_start;i < (data_size - key_size + 1);i++)
\r
115 UCHAR *p = ((UCHAR *)data) + i;
\r
117 if (Cmp(p, key, key_size) == 0)
\r
129 // これでとりあえずどのような OS 上でもプロセスは落ちるはずである
\r
133 UCHAR *c = (UCHAR *)r;
\r
140 LIST *BufToCandidate(BUF *b)
\r
151 num = ReadBufInt(b);
\r
152 o = NewCandidateList();
\r
154 for (i = 0;i < num;i++)
\r
160 sec64 = ReadBufInt64(b);
\r
161 len = ReadBufInt(b);
\r
166 size = (len + 1) * 2;
\r
167 s = ZeroMalloc(size);
\r
168 if (ReadBuf(b, s, size) != size)
\r
175 c = ZeroMalloc(sizeof(CANDIDATE));
\r
176 c->LastSelectedTime = sec64;
\r
187 BUF *CandidateToBuf(LIST *o)
\r
198 WriteBufInt(b, LIST_NUM(o));
\r
199 for (i = 0;i < LIST_NUM(o);i++)
\r
201 CANDIDATE *c = LIST_DATA(o, i);
\r
202 WriteBufInt64(b, c->LastSelectedTime);
\r
203 WriteBufInt(b, UniStrLen(c->Str));
\r
204 WriteBuf(b, c->Str, UniStrSize(c->Str));
\r
213 void AddCandidate(LIST *o, wchar_t *str, UINT num_max)
\r
218 if (o == NULL || str == NULL)
\r
224 num_max = 0x7fffffff;
\r
228 str = UniCopyStr(str);
\r
232 for (i = 0;i < LIST_NUM(o);i++)
\r
234 CANDIDATE *c = LIST_DATA(o, i);
\r
235 if (UniStrCmpi(c->Str, str) == 0)
\r
237 // 既存のものを発見したので時刻を更新する
\r
238 c->LastSelectedTime = SystemTime64();
\r
244 if (exists == false)
\r
247 CANDIDATE *c = ZeroMalloc(sizeof(CANDIDATE));
\r
248 c->LastSelectedTime = SystemTime64();
\r
249 c->Str = UniCopyStr(str);
\r
256 // 現在の候補数を調べて、num_max より多ければ
\r
258 if (LIST_NUM(o) > num_max)
\r
260 while (LIST_NUM(o) > num_max)
\r
262 UINT index = LIST_NUM(o) - 1;
\r
263 CANDIDATE *c = LIST_DATA(o, index);
\r
272 int ComapreCandidate(void *p1, void *p2)
\r
274 CANDIDATE *c1, *c2;
\r
275 if (p1 == NULL || p2 == NULL)
\r
279 c1 = *(CANDIDATE **)p1;
\r
280 c2 = *(CANDIDATE **)p2;
\r
281 if (c1 == NULL || c2 == NULL)
\r
285 if (c1->LastSelectedTime > c2->LastSelectedTime)
\r
289 else if (c1->LastSelectedTime < c2->LastSelectedTime)
\r
295 return UniStrCmpi(c1->Str, c2->Str);
\r
300 void FreeCandidateList(LIST *o)
\r
309 for (i = 0;i < LIST_NUM(o);i++)
\r
311 CANDIDATE *c = LIST_DATA(o, i);
\r
320 LIST *NewCandidateList()
\r
322 return NewList(ComapreCandidate);
\r
325 // 指定したアドレスがすべてゼロかどうか調べる
\r
326 bool IsZero(void *data, UINT size)
\r
329 UCHAR *c = (UCHAR *)data;
\r
331 if (data == NULL || size == 0)
\r
336 for (i = 0;i < size;i++)
\r
348 UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size)
\r
350 unsigned long dst_size_long = dst_size;
\r
352 if (dst == NULL || dst_size_long == 0 || src == NULL)
\r
357 if (uncompress(dst, &dst_size_long, src, src_size) != Z_OK)
\r
362 return (UINT)dst_size_long;
\r
366 UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size)
\r
368 return CompressEx(dst, dst_size, src, src_size, Z_DEFAULT_COMPRESSION);
\r
371 // データをオプション付きで圧縮する
\r
372 UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level)
\r
374 unsigned long dst_size_long = dst_size;
\r
376 if (dst == NULL || dst_size_long == 0 || src == NULL)
\r
381 if (compress2(dst, &dst_size_long, src, src_size, (int)level) != Z_OK)
\r
386 return dst_size_long;
\r
389 // src_size データを圧縮した場合の最大サイズを取得する
\r
390 UINT CalcCompress(UINT src_size)
\r
393 return src_size * 2 + 100;
\r
399 return NewSkEx(false);
\r
401 SK *NewSkEx(bool no_compact)
\r
405 s = Malloc(sizeof(SK));
\r
406 s->lock = NewLock();
\r
409 s->num_reserved = INIT_NUM_RESERVED;
\r
410 s->p = Malloc(sizeof(void *) * s->num_reserved);
\r
411 s->no_compact = no_compact;
\r
413 #ifndef DONT_USE_KERNEL_STATUS
\r
414 TrackNewObj(POINTER_TO_UINT64(s), "SK", 0);
\r
415 #endif // DONT_USE_KERNEL_STATUS
\r
418 KS_INC(KS_NEWSK_COUNT);
\r
424 void ReleaseSk(SK *s)
\r
432 if (Release(s->ref) == 0)
\r
439 void CleanupSk(SK *s)
\r
449 DeleteLock(s->lock);
\r
452 #ifndef DONT_USE_KERNEL_STATUS
\r
453 TrackDeleteObj(POINTER_TO_UINT64(s));
\r
454 #endif // DONT_USE_KERNEL_STATUS
\r
457 KS_INC(KS_FREESK_COUNT);
\r
473 void UnlockSk(SK *s)
\r
485 void Push(SK *s, void *p)
\r
489 if (s == NULL || p == NULL)
\r
498 if (s->num_item > s->num_reserved)
\r
500 s->num_reserved = s->num_reserved * 2;
\r
501 s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
\r
506 KS_INC(KS_PUSH_COUNT);
\r
518 if (s->num_item == 0)
\r
522 ret = s->p[s->num_item - 1];
\r
526 if (s->no_compact == false)
\r
528 // no_compact が true の場合は縮小しない
\r
529 if ((s->num_item * 2) <= s->num_reserved)
\r
531 if (s->num_reserved >= (INIT_NUM_RESERVED * 2))
\r
533 s->num_reserved = s->num_reserved / 2;
\r
534 s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
\r
540 KS_INC(KS_POP_COUNT);
\r
546 void *GetNext(QUEUE *q)
\r
555 if (q->num_item == 0)
\r
562 ReadFifo(q->fifo, &p, sizeof(void *));
\r
566 KS_INC(KS_GETNEXT_COUNT);
\r
572 void InsertQueueInt(QUEUE *q, UINT value)
\r
581 p = Clone(&value, sizeof(UINT));
\r
587 void InsertQueue(QUEUE *q, void *p)
\r
590 if (q == NULL || p == NULL)
\r
596 WriteFifo(q->fifo, &p, sizeof(void *));
\r
601 KS_INC(KS_INSERT_QUEUE_COUNT);
\r
605 void LockQueue(QUEUE *q)
\r
617 void UnlockQueue(QUEUE *q)
\r
629 void ReleaseQueue(QUEUE *q)
\r
637 if (q->ref == NULL || Release(q->ref) == 0)
\r
644 void CleanupQueue(QUEUE *q)
\r
653 ReleaseFifo(q->fifo);
\r
654 DeleteLock(q->lock);
\r
657 #ifndef DONT_USE_KERNEL_STATUS
\r
658 TrackDeleteObj(POINTER_TO_UINT64(q));
\r
659 #endif // DONT_USE_KERNEL_STATUS
\r
662 KS_INC(KS_FREEQUEUE_COUNT);
\r
670 q = ZeroMalloc(sizeof(QUEUE));
\r
671 q->lock = NewLock();
\r
674 q->fifo = NewFifo();
\r
676 #ifndef DONT_USE_KERNEL_STATUS
\r
677 TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
\r
678 #endif // DONT_USE_KERNEL_STATUS
\r
681 KS_INC(KS_NEWQUEUE_COUNT);
\r
685 QUEUE *NewQueueFast()
\r
689 q = ZeroMalloc(sizeof(QUEUE));
\r
693 q->fifo = NewFifoFast();
\r
695 #ifndef DONT_USE_KERNEL_STATUS
\r
696 TrackNewObj(POINTER_TO_UINT64(q), "QUEUE", 0);
\r
697 #endif // DONT_USE_KERNEL_STATUS
\r
700 KS_INC(KS_NEWQUEUE_COUNT);
\r
706 void SetCmp(LIST *o, COMPARE *cmp)
\r
709 if (o == NULL || cmp == NULL)
\r
722 LIST *CloneList(LIST *o)
\r
724 LIST *n = NewList(o->cmp);
\r
729 n->num_item = n->num_reserved = LIST_NUM(o);
\r
730 n->sorted = o->sorted;
\r
736 void CopyToArray(LIST *o, void *p)
\r
739 if (o == NULL || p == NULL)
\r
745 KS_INC(KS_TOARRAY_COUNT);
\r
747 Copy(p, o->p, sizeof(void *) * o->num_item);
\r
751 void *ToArray(LIST *o)
\r
753 return ToArrayEx(o, false);
\r
755 void *ToArrayEx(LIST *o, bool fast)
\r
767 p = Malloc(sizeof(void *) * LIST_NUM(o));
\r
771 p = MallocFast(sizeof(void *) * LIST_NUM(o));
\r
780 void *Search(LIST *o, void *target)
\r
784 if (o == NULL || target == NULL)
\r
788 if (o->cmp == NULL)
\r
794 if (o->sorted == false)
\r
800 // なんだ C ライブラリのバイナリサーチ関数を呼んでいるだけか
\r
801 ret = (void **)bsearch(&target, o->p, o->num_item, sizeof(void *),
\r
802 (int(*)(const void *, const void *))o->cmp);
\r
805 KS_INC(KS_SEARCH_COUNT);
\r
818 // 本当はもうちょっとましなデータ構造 & アルゴリズムにするべき
\r
819 void Insert(LIST *o, void *p)
\r
821 int low, high, middle;
\r
825 if (o == NULL || p == NULL)
\r
830 if (o->cmp == NULL)
\r
832 // ソート関数が無い場合は単純に追加する
\r
837 // ソートされていない場合は直ちにソートする
\r
838 if (o->sorted == false)
\r
844 high = LIST_NUM(o) - 1;
\r
848 while (low <= high)
\r
852 middle = (low + high) / 2;
\r
853 ret = o->cmp(&(o->p[middle]), &p);
\r
870 if (pos == INFINITE)
\r
876 if (o->num_item > o->num_reserved)
\r
878 o->num_reserved *= 2;
\r
879 o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
\r
882 if (LIST_NUM(o) >= 2)
\r
884 for (i = (LIST_NUM(o) - 2);i >= (int)pos;i--)
\r
886 o->p[i + 1] = o->p[i];
\r
893 KS_INC(KS_INSERT_COUNT);
\r
897 void SetSortFlag(LIST *o, bool sorted)
\r
905 o->sorted = sorted;
\r
912 if (o == NULL || o->cmp == NULL)
\r
917 qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))o->cmp);
\r
921 KS_INC(KS_SORT_COUNT);
\r
924 // ある文字列項目がリスト内に存在しているかどうか調べる (Unicode 版)
\r
925 bool IsInListUniStr(LIST *o, wchar_t *str)
\r
929 if (o == NULL || str == NULL)
\r
934 for (i = 0;i < LIST_NUM(o);i++)
\r
936 wchar_t *s = LIST_DATA(o, i);
\r
938 if (UniStrCmpi(s, str) == 0)
\r
948 bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr)
\r
952 if (o == NULL || oldptr == NULL || newptr == NULL)
\r
957 for (i = 0;i < LIST_NUM(o);i++)
\r
959 void *p = LIST_DATA(o, i);
\r
971 // ある文字列項目がリスト内に存在しているかどうか調べる
\r
972 bool IsInListStr(LIST *o, char *str)
\r
976 if (o == NULL || str == NULL)
\r
981 for (i = 0;i < LIST_NUM(o);i++)
\r
983 char *s = LIST_DATA(o, i);
\r
985 if (StrCmpi(s, str) == 0)
\r
994 // リスト内を UINT 形式のポインタで走査してポインタを取得する
\r
995 void *ListKeyToPointer(LIST *o, UINT key)
\r
999 if (o == NULL || key == 0)
\r
1004 for (i = 0;i < LIST_NUM(o);i++)
\r
1006 void *p = LIST_DATA(o, i);
\r
1008 if (POINTER_TO_KEY(p) == key)
\r
1017 // あるキーがリスト内に存在するかどうか調べる
\r
1018 bool IsInListKey(LIST *o, UINT key)
\r
1022 if (o == NULL || key == 0)
\r
1027 p = ListKeyToPointer(o, key);
\r
1036 // ある項目がリスト内に存在するかどうか調べる
\r
1037 bool IsInList(LIST *o, void *p)
\r
1041 if (o == NULL || p == NULL)
\r
1046 for (i = 0;i < LIST_NUM(o);i++)
\r
1048 void *q = LIST_DATA(o, i);
\r
1059 void Add(LIST *o, void *p)
\r
1063 if (o == NULL || p == NULL)
\r
1071 if (o->num_item > o->num_reserved)
\r
1073 o->num_reserved = o->num_reserved * 2;
\r
1074 o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
\r
1078 o->sorted = false;
\r
1081 KS_INC(KS_INSERT_COUNT);
\r
1084 // リストからキーで指定した要素の削除
\r
1085 bool DeleteKey(LIST *o, UINT key)
\r
1089 if (o == NULL || key == 0)
\r
1094 p = ListKeyToPointer(o, key);
\r
1100 return Delete(o, p);
\r
1104 bool Delete(LIST *o, void *p)
\r
1108 if (o == NULL || p == NULL)
\r
1113 for (i = 0;i < o->num_item;i++)
\r
1120 if (i == o->num_item)
\r
1126 for (i = n;i < (o->num_item - 1);i++)
\r
1128 o->p[i] = o->p[i + 1];
\r
1131 if ((o->num_item * 2) <= o->num_reserved)
\r
1133 if (o->num_reserved > (INIT_NUM_RESERVED * 2))
\r
1135 o->num_reserved = o->num_reserved / 2;
\r
1136 o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
\r
1141 KS_INC(KS_DELETE_COUNT);
\r
1147 void DeleteAll(LIST *o)
\r
1156 o->num_reserved = INIT_NUM_RESERVED;
\r
1157 o->p = ReAlloc(o->p, sizeof(void *) * INIT_NUM_RESERVED);
\r
1161 void LockList(LIST *o)
\r
1173 void UnlockList(LIST *o)
\r
1185 void ReleaseList(LIST *o)
\r
1193 if (o->ref == NULL || Release(o->ref) == 0)
\r
1200 void CleanupList(LIST *o)
\r
1209 if (o->lock != NULL)
\r
1211 DeleteLock(o->lock);
\r
1216 KS_INC(KS_FREELIST_COUNT);
\r
1218 #ifndef DONT_USE_KERNEL_STATUS
\r
1219 TrackDeleteObj(POINTER_TO_UINT64(o));
\r
1220 #endif // DONT_USE_KERNEL_STATUS
\r
1223 // 文字列比較関数 (Unicode)
\r
1224 int CompareUniStr(void *p1, void *p2)
\r
1227 if (p1 == NULL || p2 == NULL)
\r
1231 s1 = *(wchar_t **)p1;
\r
1232 s2 = *(wchar_t **)p2;
\r
1234 return UniStrCmp(s1, s2);
\r
1238 bool InsertStr(LIST *o, char *str)
\r
1241 if (o == NULL || str == NULL)
\r
1246 if (Search(o, str) == NULL)
\r
1257 int CompareStr(void *p1, void *p2)
\r
1260 if (p1 == NULL || p2 == NULL)
\r
1264 s1 = *(char **)p1;
\r
1265 s2 = *(char **)p2;
\r
1267 return StrCmpi(s1, s2);
\r
1270 // 高速リスト (ロック無し) の作成
\r
1271 LIST *NewListFast(COMPARE *cmp)
\r
1273 return NewListEx(cmp, true);
\r
1277 LIST *NewList(COMPARE *cmp)
\r
1279 return NewListEx(cmp, false);
\r
1281 LIST *NewListEx(COMPARE *cmp, bool fast)
\r
1283 return NewListEx2(cmp, fast, false);
\r
1285 LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc)
\r
1289 if (fast_malloc == false)
\r
1291 o = Malloc(sizeof(LIST));
\r
1295 o = MallocFast(sizeof(LIST));
\r
1298 if (fast == false)
\r
1300 o->lock = NewLock();
\r
1301 o->ref = NewRef();
\r
1309 o->num_reserved = INIT_NUM_RESERVED;
\r
1311 if (fast_malloc == false)
\r
1313 o->p = Malloc(sizeof(void *) * o->num_reserved);
\r
1317 o->p = MallocFast(sizeof(void *) * o->num_reserved);
\r
1323 #ifndef DONT_USE_KERNEL_STATUS
\r
1324 TrackNewObj(POINTER_TO_UINT64(o), "LIST", 0);
\r
1325 #endif //DONT_USE_KERNEL_STATUS
\r
1328 KS_INC(KS_NEWLIST_COUNT);
\r
1333 // FIFO から peek する
\r
1334 UINT PeekFifo(FIFO *f, void *p, UINT size)
\r
1337 if (f == NULL || size == 0)
\r
1343 KS_INC(KS_PEEK_FIFO_COUNT);
\r
1345 read_size = MIN(size, f->size);
\r
1346 if (read_size == 0)
\r
1353 Copy(p, (UCHAR *)f->p + f->pos, read_size);
\r
1360 UINT ReadFifo(FIFO *f, void *p, UINT size)
\r
1364 if (f == NULL || size == 0)
\r
1369 read_size = MIN(size, f->size);
\r
1370 if (read_size == 0)
\r
1376 Copy(p, (UCHAR *)f->p + f->pos, read_size);
\r
1378 f->pos += read_size;
\r
1379 f->size -= read_size;
\r
1387 if (f->pos >= FIFO_INIT_MEM_SIZE &&
\r
1388 f->memsize >= f->realloc_mem_size &&
\r
1389 (f->memsize / 2) > f->size)
\r
1394 new_size = MAX(f->memsize / 2, FIFO_INIT_MEM_SIZE);
\r
1395 new_p = Malloc(new_size);
\r
1396 Copy(new_p, (UCHAR *)f->p + f->pos, f->size);
\r
1400 f->memsize = new_size;
\r
1406 KS_INC(KS_READ_FIFO_COUNT);
\r
1412 void WriteFifo(FIFO *f, void *p, UINT size)
\r
1414 UINT i, need_size;
\r
1415 bool realloc_flag;
\r
1417 if (f == NULL || size == 0)
\r
1424 need_size = f->pos + f->size;
\r
1425 realloc_flag = false;
\r
1428 while (need_size > f->memsize)
\r
1430 f->memsize = MAX(f->memsize, FIFO_INIT_MEM_SIZE) * 3;
\r
1431 realloc_flag = true;
\r
1436 f->p = ReAlloc(f->p, f->memsize);
\r
1442 Copy((UCHAR *)f->p + f->pos + i, p, size);
\r
1446 KS_INC(KS_WRITE_FIFO_COUNT);
\r
1450 void ClearFifo(FIFO *f)
\r
1458 f->size = f->pos = 0;
\r
1459 f->memsize = FIFO_INIT_MEM_SIZE;
\r
1460 f->p = ReAlloc(f->p, f->memsize);
\r
1464 UINT FifoSize(FIFO *f)
\r
1476 void LockFifo(FIFO *f)
\r
1488 void UnlockFifo(FIFO *f)
\r
1500 void ReleaseFifo(FIFO *f)
\r
1508 if (f->ref == NULL || Release(f->ref) == 0)
\r
1515 void CleanupFifo(FIFO *f)
\r
1523 DeleteLock(f->lock);
\r
1527 #ifndef DONT_USE_KERNEL_STATUS
\r
1528 TrackDeleteObj(POINTER_TO_UINT64(f));
\r
1529 #endif //DONT_USE_KERNEL_STATUS
\r
1532 KS_INC(KS_FREEFIFO_COUNT);
\r
1538 fifo_default_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
\r
1544 return NewFifoEx(0, false);
\r
1546 FIFO *NewFifoFast()
\r
1548 return NewFifoEx(0, true);
\r
1550 FIFO *NewFifoEx(UINT realloc_mem_size, bool fast)
\r
1555 f = Malloc(sizeof(FIFO));
\r
1557 if (fast == false)
\r
1559 f->lock = NewLock();
\r
1560 f->ref = NewRef();
\r
1568 f->size = f->pos = 0;
\r
1569 f->memsize = FIFO_INIT_MEM_SIZE;
\r
1570 f->p = Malloc(FIFO_INIT_MEM_SIZE);
\r
1572 if (realloc_mem_size == 0)
\r
1574 realloc_mem_size = fifo_default_realloc_mem_size;
\r
1577 f->realloc_mem_size = realloc_mem_size;
\r
1579 #ifndef DONT_USE_KERNEL_STATUS
\r
1580 TrackNewObj(POINTER_TO_UINT64(f), "FIFO", 0);
\r
1581 #endif // DONT_USE_KERNEL_STATUS
\r
1584 KS_INC(KS_NEWFIFO_COUNT);
\r
1589 // FIFO のデフォルトのメモリ再確保サイズを取得する
\r
1590 UINT GetFifoDefaultReallocMemSize()
\r
1592 return fifo_default_realloc_mem_size;
\r
1595 // FIFO のデフォルトのメモリ再確保サイズを設定する
\r
1596 void SetFifoDefaultReallocMemSize(UINT size)
\r
1600 size = FIFO_REALLOC_MEM_SIZE;
\r
1603 fifo_default_realloc_mem_size = size;
\r
1606 // バッファをファイルから読み込む
\r
1607 BUF *FileToBuf(IO *o)
\r
1609 UCHAR hash1[MD5_SIZE], hash2[MD5_SIZE];
\r
1621 if (FileRead(o, &size, sizeof(size)) == false)
\r
1625 size = Endian32(size);
\r
1627 if (size > FileSize(o))
\r
1633 if (FileRead(o, hash1, sizeof(hash1)) == false)
\r
1639 buf = Malloc(size);
\r
1640 if (FileRead(o, buf, size) == false)
\r
1647 Hash(hash2, buf, size, false);
\r
1650 if (Cmp(hash1, hash2, sizeof(hash1)) != 0)
\r
1659 WriteBuf(b, buf, size);
\r
1666 // ダンプファイルをバッファに読み込む
\r
1667 BUF *ReadDump(char *filename)
\r
1674 if (filename == NULL)
\r
1679 o = FileOpen(filename, false);
\r
1685 size = FileSize(o);
\r
1686 data = Malloc(size);
\r
1687 FileRead(o, data, size);
\r
1691 WriteBuf(b, data, size);
\r
1697 BUF *ReadDumpW(wchar_t *filename)
\r
1704 if (filename == NULL)
\r
1709 o = FileOpenW(filename, false);
\r
1715 size = FileSize(o);
\r
1716 data = Malloc(size);
\r
1717 FileRead(o, data, size);
\r
1721 WriteBuf(b, data, size);
\r
1728 // バッファ内容をファイルにダンプする
\r
1729 bool DumpBuf(BUF *b, char *filename)
\r
1733 if (b == NULL || filename == NULL)
\r
1738 o = FileCreate(filename);
\r
1743 FileWrite(o, b->Buf, b->Size);
\r
1748 bool DumpBufW(BUF *b, wchar_t *filename)
\r
1752 if (b == NULL || filename == NULL)
\r
1757 o = FileCreateW(filename);
\r
1762 FileWrite(o, b->Buf, b->Size);
\r
1769 bool BufToFile(IO *o, BUF *b)
\r
1771 UCHAR hash[MD5_SIZE];
\r
1775 if (o == NULL || b == NULL)
\r
1781 Hash(hash, b->Buf, b->Size, false);
\r
1783 size = Endian32(b->Size);
\r
1786 if (FileWrite(o, &size, sizeof(size)) == false)
\r
1792 if (FileWrite(o, hash, sizeof(hash)) == false)
\r
1798 if (FileWrite(o, b->Buf, b->Size) == false)
\r
1812 b = Malloc(sizeof(BUF));
\r
1813 b->Buf = Malloc(INIT_BUF_SIZE);
\r
1816 b->SizeReserved = INIT_BUF_SIZE;
\r
1818 #ifndef DONT_USE_KERNEL_STATUS
\r
1819 TrackNewObj(POINTER_TO_UINT64(b), "BUF", 0);
\r
1820 #endif // DONT_USE_KERNEL_STATUS
\r
1823 KS_INC(KS_NEWBUF_COUNT);
\r
1824 KS_INC(KS_CURRENT_BUF_COUNT);
\r
1830 void ClearBuf(BUF *b)
\r
1843 void WriteBuf(BUF *b, void *buf, UINT size)
\r
1847 if (b == NULL || buf == NULL || size == 0)
\r
1852 new_size = b->Current + size;
\r
1853 if (new_size > b->Size)
\r
1856 AdjustBufSize(b, new_size);
\r
1858 if (b->Buf != NULL)
\r
1860 Copy((UCHAR *)b->Buf + b->Current, buf, size);
\r
1862 b->Current += size;
\r
1863 b->Size = new_size;
\r
1866 KS_INC(KS_WRITE_BUF_COUNT);
\r
1870 void AddBufStr(BUF *b, char *str)
\r
1873 if (b == NULL || str == NULL)
\r
1878 WriteBuf(b, str, StrLen(str));
\r
1882 void WriteBufLine(BUF *b, char *str)
\r
1884 char *crlf = "\r\n";
\r
1886 if (b == NULL || str == NULL)
\r
1891 WriteBuf(b, str, StrLen(str));
\r
1892 WriteBuf(b, crlf, StrLen(crlf));
\r
1896 bool WriteBufStr(BUF *b, char *str)
\r
1900 if (b == NULL || str == NULL)
\r
1906 len = StrLen(str);
\r
1907 if (WriteBufInt(b, len + 1) == false)
\r
1913 WriteBuf(b, str, len);
\r
1919 bool ReadBufStr(BUF *b, char *str, UINT size)
\r
1924 if (b == NULL || str == NULL || size == 0)
\r
1930 len = ReadBufInt(b);
\r
1936 if (len <= (size - 1))
\r
1941 read_size = MIN(len, (size - 1));
\r
1944 if (ReadBuf(b, str, read_size) != read_size)
\r
1948 if (read_size < len)
\r
1950 ReadBuf(b, NULL, len - read_size);
\r
1952 str[read_size] = 0;
\r
1957 // バッファに 64 bit 整数を書き込む
\r
1958 bool WriteBufInt64(BUF *b, UINT64 value)
\r
1966 value = Endian64(value);
\r
1968 WriteBuf(b, &value, sizeof(UINT64));
\r
1973 bool WriteBufInt(BUF *b, UINT value)
\r
1981 value = Endian32(value);
\r
1983 WriteBuf(b, &value, sizeof(UINT));
\r
1987 // バッファから 64bit 整数を読み込む
\r
1988 UINT64 ReadBufInt64(BUF *b)
\r
1997 if (ReadBuf(b, &value, sizeof(UINT64)) != sizeof(UINT64))
\r
2001 return Endian64(value);
\r
2005 UINT ReadBufInt(BUF *b)
\r
2014 if (ReadBuf(b, &value, sizeof(UINT)) != sizeof(UINT))
\r
2018 return Endian32(value);
\r
2022 void WriteBufBuf(BUF *b, BUF *bb)
\r
2025 if (b == NULL || bb == NULL)
\r
2030 WriteBuf(b, bb->Buf, bb->Size);
\r
2033 // バッファからバッファを読み込み
\r
2034 BUF *ReadBufFromBuf(BUF *b, UINT size)
\r
2044 data = Malloc(size);
\r
2045 if (ReadBuf(b, data, size) != size)
\r
2052 WriteBuf(ret, data, size);
\r
2053 SeekBuf(ret, 0, 0);
\r
2061 UINT ReadBuf(BUF *b, void *buf, UINT size)
\r
2065 if (b == NULL || size == 0)
\r
2070 if (b->Buf == NULL)
\r
2076 if ((b->Current + size) >= b->Size)
\r
2078 size_read = b->Size - b->Current;
\r
2081 Zero((UCHAR *)buf + size_read, size - size_read);
\r
2087 Copy(buf, (UCHAR *)b->Buf + b->Current, size_read);
\r
2090 b->Current += size_read;
\r
2093 KS_INC(KS_READ_BUF_COUNT);
\r
2099 void AdjustBufSize(BUF *b, UINT new_size)
\r
2107 if (b->SizeReserved >= new_size)
\r
2112 while (b->SizeReserved < new_size)
\r
2114 b->SizeReserved = b->SizeReserved * 2;
\r
2116 b->Buf = ReAlloc(b->Buf, b->SizeReserved);
\r
2119 KS_INC(KS_ADJUST_BUFSIZE_COUNT);
\r
2123 void SeekBuf(BUF *b, UINT offset, int mode)
\r
2142 new_pos = b->Current + offset;
\r
2147 if (b->Current >= offset)
\r
2149 new_pos = b->Current - offset;
\r
2157 b->Current = MAKESURE(new_pos, 0, b->Size);
\r
2159 KS_INC(KS_SEEK_BUF_COUNT);
\r
2163 void FreeBuf(BUF *b)
\r
2176 KS_INC(KS_FREEBUF_COUNT);
\r
2177 KS_DEC(KS_CURRENT_BUF_COUNT);
\r
2179 #ifndef DONT_USE_KERNEL_STATUS
\r
2180 TrackDeleteObj(POINTER_TO_UINT64(b));
\r
2181 #endif // DONT_USE_KERNEL_STATUS
\r
2184 // Unicode 文字列のエンディアン変換
\r
2185 void EndianUnicode(wchar_t *str)
\r
2193 len = UniStrLen(str);
\r
2195 for (i = 0;i < len;i++)
\r
2197 str[i] = Endian16(str[i]);
\r
2202 USHORT Endian16(USHORT src)
\r
2205 if (*((char *)&x))
\r
2207 return Swap16(src);
\r
2216 UINT Endian32(UINT src)
\r
2219 if (*((char *)&x))
\r
2221 return Swap32(src);
\r
2230 UINT64 Endian64(UINT64 src)
\r
2233 if (*((char *)&x))
\r
2235 return Swap64(src);
\r
2244 void Swap(void *buf, UINT size)
\r
2249 if (buf == NULL || size == 0)
\r
2254 src = (UCHAR *)buf;
\r
2255 tmp = Malloc(size);
\r
2256 for (i = 0;i < size;i++)
\r
2258 tmp[size - i - 1] = src[i];
\r
2261 Copy(buf, tmp, size);
\r
2266 USHORT Swap16(USHORT value)
\r
2270 ((BYTE *)&r)[0] = ((BYTE *)&value)[1];
\r
2271 ((BYTE *)&r)[1] = ((BYTE *)&value)[0];
\r
2276 UINT Swap32(UINT value)
\r
2280 ((BYTE *)&r)[0] = ((BYTE *)&value)[3];
\r
2281 ((BYTE *)&r)[1] = ((BYTE *)&value)[2];
\r
2282 ((BYTE *)&r)[2] = ((BYTE *)&value)[1];
\r
2283 ((BYTE *)&r)[3] = ((BYTE *)&value)[0];
\r
2288 UINT64 Swap64(UINT64 value)
\r
2292 ((BYTE *)&r)[0] = ((BYTE *)&value)[7];
\r
2293 ((BYTE *)&r)[1] = ((BYTE *)&value)[6];
\r
2294 ((BYTE *)&r)[2] = ((BYTE *)&value)[5];
\r
2295 ((BYTE *)&r)[3] = ((BYTE *)&value)[4];
\r
2296 ((BYTE *)&r)[4] = ((BYTE *)&value)[3];
\r
2297 ((BYTE *)&r)[5] = ((BYTE *)&value)[2];
\r
2298 ((BYTE *)&r)[6] = ((BYTE *)&value)[1];
\r
2299 ((BYTE *)&r)[7] = ((BYTE *)&value)[0];
\r
2304 UINT Encode64(char *dst, char *src)
\r
2307 if (dst == NULL || src == NULL)
\r
2312 return B64_Encode(dst, src, StrLen(src));
\r
2316 UINT Decode64(char *dst, char *src)
\r
2319 if (dst == NULL || src == NULL)
\r
2324 return B64_Decode(dst, src, StrLen(src));
\r
2328 int B64_Encode(char *set, char *source, int len)
\r
2332 src = (BYTE *)source;
\r
2347 set[j] = B64_CodeToChar((src[i]) >> 2);
\r
2353 set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);
\r
2361 set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));
\r
2367 set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);
\r
2374 set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));
\r
2375 set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);
\r
2383 int B64_Decode(char *set, char *source, int len)
\r
2394 f1 = f2 = f3 = f4 = 0;
\r
2400 a1 = B64_CharToCode(src[i]);
\r
2411 a2 = B64_CharToCode(src[i + 1]);
\r
2424 a3 = B64_CharToCode(src[i + 2]);
\r
2437 a4 = B64_CharToCode(src[i + 3]);
\r
2448 set[j] = (a1 << 2) + (a2 >> 4);
\r
2456 set[j] = (a2 << 4) + (a3 >> 2);
\r
2464 set[j] = (a3 << 6) + a4;
\r
2473 // Base64 - コードを文字に変換
\r
2474 char B64_CodeToChar(BYTE c)
\r
2482 if (c >= 0x1a && c <= 0x33)
\r
2484 r = c - 0x1a + 'a';
\r
2486 if (c >= 0x34 && c <= 0x3d)
\r
2488 r = c - 0x34 + '0';
\r
2501 // Base64 - 文字をコードに変換
\r
2502 char B64_CharToCode(char c)
\r
2504 if (c >= 'A' && c <= 'Z')
\r
2508 if (c >= 'a' && c <= 'z')
\r
2510 return c - 'a' + 0x1a;
\r
2512 if (c >= '0' && c <= '9')
\r
2514 return c - '0' + 0x34;
\r
2531 // 高速な Malloc (現在未実装)
\r
2532 // 実は小さなバッファをたくさんまとめておいてそれを動的に割り当てるコードを昔
\r
2533 // 書いたのだが、Windows, Linux, Solaris で試しても普通の malloc() と比べて
\r
2534 // ほとんど速度に影響がなかったので、やめにした。
\r
2535 void *MallocFast(UINT size)
\r
2537 return Malloc(size);
\r
2541 void *Malloc(UINT size)
\r
2543 return MallocEx(size, false);
\r
2545 void *MallocEx(UINT size, bool zero_clear_when_free)
\r
2550 real_size = CALC_MALLOCSIZE(size);
\r
2552 tag = InternalMalloc(real_size);
\r
2554 Zero(tag, sizeof(MEMTAG));
\r
2555 tag->Magic = MEMTAG_MAGIC;
\r
2557 tag->ZeroFree = zero_clear_when_free;
\r
2559 return MEMTAG_TO_POINTER(tag);
\r
2563 void *ReAlloc(void *addr, UINT size)
\r
2568 if (IS_NULL_POINTER(addr))
\r
2573 tag = POINTER_TO_MEMTAG(addr);
\r
2576 zerofree = tag->ZeroFree;
\r
2578 if (tag->Size == size)
\r
2587 // サイズ変更有り (ゼロクリア必須)
\r
2588 void *new_p = MallocEx(size, true);
\r
2590 if (tag->Size <= size)
\r
2593 Copy(new_p, addr, tag->Size);
\r
2598 Copy(new_p, addr, size);
\r
2609 MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));
\r
2611 Zero(tag2, sizeof(MEMTAG));
\r
2612 tag2->Magic = MEMTAG_MAGIC;
\r
2613 tag2->Size = size;
\r
2615 return MEMTAG_TO_POINTER(tag2);
\r
2621 void Free(void *addr)
\r
2625 if (IS_NULL_POINTER(addr))
\r
2630 tag = POINTER_TO_MEMTAG(addr);
\r
2633 if (tag->ZeroFree)
\r
2636 Zero(addr, tag->Size);
\r
2641 InternalFree(tag);
\r
2645 void CheckMemTag(MEMTAG *tag)
\r
2647 #ifndef DONT_CHECK_HEAP
\r
2651 AbortExitEx("CheckMemTag: tag == NULL");
\r
2655 if (tag->Magic != MEMTAG_MAGIC)
\r
2657 AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");
\r
2660 #endif // DONT_CHECK_HEAP
\r
2664 void *ZeroMalloc(UINT size)
\r
2666 return ZeroMallocEx(size, false);
\r
2668 void *ZeroMallocEx(UINT size, bool zero_clear_when_free)
\r
2670 void *p = MallocEx(size, zero_clear_when_free);
\r
2674 void *ZeroMallocFast(UINT size)
\r
2676 void *p = MallocFast(size);
\r
2682 void *InternalMalloc(UINT size)
\r
2686 size = MORE(size, 1);
\r
2689 KS_INC(KS_MALLOC_COUNT);
\r
2690 KS_INC(KS_TOTAL_MEM_COUNT);
\r
2691 KS_ADD(KS_TOTAL_MEM_SIZE, size);
\r
2692 KS_INC(KS_CURRENT_MEM_COUNT);
\r
2694 // メモリが確保されるまで試行する
\r
2697 if ((retry++) > MEMORY_MAX_RETRY)
\r
2699 AbortExitEx("InternalMalloc: error: malloc() failed.\n\n");
\r
2701 addr = OSMemoryAlloc(size);
\r
2707 OSSleep(MEMORY_SLEEP_TIME);
\r
2710 #ifndef DONT_USE_KERNEL_STATUS
\r
2711 TrackNewObj(POINTER_TO_UINT64(addr), "MEM", size);
\r
2712 #endif //DONT_USE_KERNEL_STATUS
\r
2718 void InternalFree(void *addr)
\r
2727 KS_DEC(KS_CURRENT_MEM_COUNT);
\r
2728 KS_INC(KS_FREE_COUNT);
\r
2730 #ifndef DONT_USE_KERNEL_STATUS
\r
2731 TrackDeleteObj(POINTER_TO_UINT64(addr));
\r
2732 #endif // DONT_USE_KERNEL_STATUS
\r
2735 OSMemoryFree(addr);
\r
2739 void *InternalReAlloc(void *addr, UINT size)
\r
2743 size = MORE(size, 1);
\r
2746 KS_INC(KS_REALLOC_COUNT);
\r
2747 KS_ADD(KS_TOTAL_MEM_SIZE, size);
\r
2749 // メモリが確保されるまで試行する
\r
2752 if ((retry++) > MEMORY_MAX_RETRY)
\r
2754 AbortExitEx("InternalReAlloc: error: realloc() failed.\n\n");
\r
2756 new_addr = OSMemoryReAlloc(addr, size);
\r
2757 if (new_addr != NULL)
\r
2762 OSSleep(MEMORY_SLEEP_TIME);
\r
2765 #ifndef DONT_USE_KERNEL_STATUS
\r
2766 TrackChangeObjSize((DWORD)addr, size, (DWORD)new_addr);
\r
2767 #endif // DONT_USE_KERNEL_STATUS
\r
2773 void *Clone(void *addr, UINT size)
\r
2782 ret = Malloc(size);
\r
2783 Copy(ret, addr, size);
\r
2789 void Copy(void *dst, void *src, UINT size)
\r
2792 if (dst == NULL || src == NULL || size == 0 || dst == src)
\r
2798 KS_INC(KS_COPY_COUNT);
\r
2800 memcpy(dst, src, size);
\r
2804 int Cmp(void *p1, void *p2, UINT size)
\r
2807 if (p1 == NULL || p2 == NULL || size == 0)
\r
2812 return memcmp(p1, p2, (size_t)size);
\r
2816 void Zero(void *addr, UINT size)
\r
2818 ZeroMem(addr, size);
\r
2820 void ZeroMem(void *addr, UINT size)
\r
2823 if (addr == NULL || size == 0)
\r
2829 KS_INC(KS_ZERO_COUNT);
\r
2831 memset(addr, 0, size);
\r
2835 int StrMapCmp(void *p1, void *p2)
\r
2837 STRMAP_ENTRY *s1, *s2;
\r
2838 if (p1 == NULL || p2 == NULL)
\r
2842 s1 = *(STRMAP_ENTRY **)p1;
\r
2843 s2 = *(STRMAP_ENTRY **)p2;
\r
2844 if (s1 == NULL || s2 == NULL)
\r
2848 return StrCmpi(s1->Name, s2->Name);
\r
2851 // 文字列マップ(文字列で検索できるデータ)の作成
\r
2854 return NewList(StrMapCmp);
\r
2858 void *StrMapSearch(LIST *map, char *key)
\r
2860 STRMAP_ENTRY tmp, *result;
\r
2862 result = (STRMAP_ENTRY*)Search(map, &tmp);
\r
2863 if(result != NULL)
\r
2865 return result->Value;
\r