1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Mayaqua Kernel
3 
4 
5 // Memory.c
6 // Memory management program
7 
8 #include "Memory.h"
9 
10 #include "Encrypt.h"
11 #include "FileIO.h"
12 #include "Internat.h"
13 #include "Kernel.h"
14 #include "Mayaqua.h"
15 #include "Object.h"
16 #include "OS.h"
17 #include "Str.h"
18 #include "Tracking.h"
19 
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include <zlib.h>
24 
25 #define	MEMORY_SLEEP_TIME		150
26 #define	MEMORY_MAX_RETRY		30
27 #define	INIT_BUF_SIZE			10240
28 
29 #define	FIFO_INIT_MEM_SIZE		4096
30 #define	FIFO_REALLOC_MEM_SIZE	(65536 * 10)	// Exquisite value
31 
32 #define	INIT_NUM_RESERVED		32
33 
34 static UINT fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
35 
36 // New PRand
NewPRand(void * key,UINT key_size)37 PRAND *NewPRand(void *key, UINT key_size)
38 {
39 	PRAND *r;
40 	UCHAR dummy[256];
41 	if (key == NULL || key_size == 0)
42 	{
43 		key = "DUMMY";
44 		key_size = 5;
45 	}
46 
47 	r = ZeroMalloc(sizeof(PRAND));
48 
49 	Sha1(r->Key, key, key_size);
50 
51 	r->Rc4 = NewCrypt(key, key_size);
52 
53 	Zero(dummy, sizeof(dummy));
54 
55 	Encrypt(r->Rc4, dummy, dummy, 256);
56 
57 	return r;
58 }
59 
60 // Free PRand
FreePRand(PRAND * r)61 void FreePRand(PRAND *r)
62 {
63 	if (r == NULL)
64 	{
65 		return;
66 	}
67 
68 	FreeCrypt(r->Rc4);
69 
70 	Free(r);
71 }
72 
73 // Generate PRand
PRand(PRAND * p,void * data,UINT size)74 void PRand(PRAND *p, void *data, UINT size)
75 {
76 	if (p == NULL)
77 	{
78 		return;
79 	}
80 
81 	Zero(data, size);
82 
83 	Encrypt(p->Rc4, data, data, size);
84 }
85 
86 // Generate UINT PRand
PRandInt(PRAND * p)87 UINT PRandInt(PRAND *p)
88 {
89 	UINT r;
90 	if (p == NULL)
91 	{
92 		return 0;
93 	}
94 
95 	PRand(p, &r, sizeof(UINT));
96 
97 	return r;
98 }
99 
100 // Check whether the specified key item is in the hash list
IsInHashListKey(HASH_LIST * h,UINT key)101 bool IsInHashListKey(HASH_LIST *h, UINT key)
102 {
103 	// Validate arguments
104 	if (h == NULL || key == 0)
105 	{
106 		return false;
107 	}
108 
109 	if (HashListKeyToPointer(h, key) == NULL)
110 	{
111 		return false;
112 	}
113 
114 	return true;
115 }
116 
117 // Search the item in the hash list with the key
HashListKeyToPointer(HASH_LIST * h,UINT key)118 void *HashListKeyToPointer(HASH_LIST *h, UINT key)
119 {
120 	UINT num, i;
121 	void **pp;
122 	void *ret = NULL;
123 	// Validate arguments
124 	if (h == NULL || key == 0)
125 	{
126 		return NULL;
127 	}
128 
129 	pp = HashListToArray(h, &num);
130 	if (pp == NULL)
131 	{
132 		return NULL;
133 	}
134 
135 	for (i = 0;i < num;i++)
136 	{
137 		void *p = pp[i];
138 
139 		if (POINTER_TO_KEY(p) == key)
140 		{
141 			ret = p;
142 		}
143 	}
144 
145 	Free(pp);
146 
147 	return ret;
148 }
149 
150 // Lock the hash list
LockHashList(HASH_LIST * h)151 void LockHashList(HASH_LIST *h)
152 {
153 	// Validate arguments
154 	if (h == NULL)
155 	{
156 		return;
157 	}
158 
159 	Lock(h->Lock);
160 }
161 
162 // Unlock the hash list
UnlockHashList(HASH_LIST * h)163 void UnlockHashList(HASH_LIST *h)
164 {
165 	// Validate arguments
166 	if (h == NULL)
167 	{
168 		return;
169 	}
170 
171 	Unlock(h->Lock);
172 }
173 
174 // Write the contents of the hash list to array
HashListToArray(HASH_LIST * h,UINT * num)175 void **HashListToArray(HASH_LIST *h, UINT *num)
176 {
177 	void **ret = NULL;
178 	UINT i;
179 	UINT n = 0;
180 	// Validate arguments
181 	if (h == NULL || num == NULL)
182 	{
183 		if (num != NULL)
184 		{
185 			*num = 0;
186 		}
187 		return NULL;
188 	}
189 
190 	if (h->AllList != NULL)
191 	{
192 		*num = LIST_NUM(h->AllList);
193 
194 		return ToArray(h->AllList);
195 	}
196 
197 	ret = ZeroMalloc(sizeof(void *) * h->NumItems);
198 
199 	for (i = 0;i < h->Size;i++)
200 	{
201 		LIST *o = h->Entries[i];
202 
203 		if (o != NULL)
204 		{
205 			UINT j;
206 
207 			for (j = 0;j < LIST_NUM(o);j++)
208 			{
209 				void *p = LIST_DATA(o, j);
210 
211 				ret[n] = p;
212 				n++;
213 			}
214 		}
215 	}
216 
217 	*num = n;
218 
219 	return ret;
220 }
221 
222 // Search an item in the hash list
SearchHash(HASH_LIST * h,void * t)223 void *SearchHash(HASH_LIST *h, void *t)
224 {
225 	UINT r;
226 	void *ret = NULL;
227 	// Validate arguments
228 	if (h == NULL || t == NULL)
229 	{
230 		return NULL;
231 	}
232 
233 	r = CalcHashForHashList(h, t);
234 
235 	if (h->Entries[r] != NULL)
236 	{
237 		LIST *o = h->Entries[r];
238 		void *r = Search(o, t);
239 
240 		if (r != NULL)
241 		{
242 			ret = r;
243 		}
244 	}
245 
246 	return ret;
247 }
248 
249 // Remove an item from the hash list
DeleteHash(HASH_LIST * h,void * p)250 bool DeleteHash(HASH_LIST *h, void *p)
251 {
252 	UINT r;
253 	bool ret = false;
254 	// Validate arguments
255 	if (h == NULL || p == NULL)
256 	{
257 		return false;
258 	}
259 
260 	r = CalcHashForHashList(h, p);
261 
262 	if (h->Entries[r] != NULL)
263 	{
264 		if (Delete(h->Entries[r], p))
265 		{
266 			ret = true;
267 			h->NumItems--;
268 		}
269 
270 		if (LIST_NUM(h->Entries[r]) == 0)
271 		{
272 			ReleaseList(h->Entries[r]);
273 			h->Entries[r] = NULL;
274 		}
275 	}
276 
277 	if (ret)
278 	{
279 		if (h->AllList != NULL)
280 		{
281 			Delete(h->AllList, p);
282 		}
283 	}
284 
285 	return ret;
286 }
287 
288 // Add an item to the hash list
AddHash(HASH_LIST * h,void * p)289 void AddHash(HASH_LIST *h, void *p)
290 {
291 	UINT r;
292 	// Validate arguments
293 	if (h == NULL || p == NULL)
294 	{
295 		return;
296 	}
297 
298 	r = CalcHashForHashList(h, p);
299 
300 	if (h->Entries[r] == NULL)
301 	{
302 		h->Entries[r] = NewListFast(h->CompareProc);
303 	}
304 
305 	Insert(h->Entries[r], p);
306 
307 	if (h->AllList != NULL)
308 	{
309 		Add(h->AllList, p);
310 	}
311 
312 	h->NumItems++;
313 }
314 
315 // Calculation of the hash value of the object
CalcHashForHashList(HASH_LIST * h,void * p)316 UINT CalcHashForHashList(HASH_LIST *h, void *p)
317 {
318 	UINT r;
319 	// Validate arguments
320 	if (h == NULL || p == NULL)
321 	{
322 		return 0;
323 	}
324 
325 	r = h->GetHashProc(p);
326 
327 	return (r % h->Size);
328 }
329 
330 // Creating a hash list
NewHashList(GET_HASH * get_hash_proc,COMPARE * compare_proc,UINT bits,bool make_list)331 HASH_LIST *NewHashList(GET_HASH *get_hash_proc, COMPARE *compare_proc, UINT bits, bool make_list)
332 {
333 	HASH_LIST *h;
334 	// Validate arguments
335 	if (get_hash_proc == NULL || compare_proc == NULL)
336 	{
337 		return NULL;
338 	}
339 	if (bits == 0)
340 	{
341 		bits = 16;
342 	}
343 
344 	bits = MIN(bits, 31);
345 
346 	h = ZeroMalloc(sizeof(HASH_LIST));
347 
348 	h->Bits = bits;
349 	h->Size = Power(2, bits);
350 
351 	h->Lock = NewLock();
352 	h->Ref = NewRef();
353 
354 	h->Entries = ZeroMalloc(sizeof(LIST *) * h->Size);
355 
356 	h->GetHashProc = get_hash_proc;
357 	h->CompareProc = compare_proc;
358 
359 	if (make_list)
360 	{
361 		h->AllList = NewListFast(NULL);
362 	}
363 
364 	return h;
365 }
366 
367 // Release the hash list
ReleaseHashList(HASH_LIST * h)368 void ReleaseHashList(HASH_LIST *h)
369 {
370 	// Validate arguments
371 	if (h == NULL)
372 	{
373 		return;
374 	}
375 
376 	if (Release(h->Ref) == 0)
377 	{
378 		CleanupHashList(h);
379 	}
380 }
CleanupHashList(HASH_LIST * h)381 void CleanupHashList(HASH_LIST *h)
382 {
383 	UINT i;
384 	// Validate arguments
385 	if (h == NULL)
386 	{
387 		return;
388 	}
389 
390 	for (i = 0;i < h->Size;i++)
391 	{
392 		LIST *o = h->Entries[i];
393 
394 		if (o != NULL)
395 		{
396 			ReleaseList(o);
397 		}
398 	}
399 
400 	Free(h->Entries);
401 
402 	DeleteLock(h->Lock);
403 
404 	if (h->AllList != NULL)
405 	{
406 		ReleaseList(h->AllList);
407 	}
408 
409 	Free(h);
410 }
411 
412 // Append a string to the buffer
AppendBufStr(BUF * b,char * str)413 void AppendBufStr(BUF *b, char *str)
414 {
415 	// Validate arguments
416 	if (b == NULL || str == NULL)
417 	{
418 		return;
419 	}
420 
421 	WriteBuf(b, str, StrLen(str));
422 }
423 
424 // Add a UTF-8 string to the buffer
AppendBufUtf8(BUF * b,wchar_t * str)425 void AppendBufUtf8(BUF *b, wchar_t *str)
426 {
427 	UINT size;
428 	UCHAR *data;
429 	// Validate arguments
430 	if (b == NULL || str == NULL)
431 	{
432 		return;
433 	}
434 
435 	size = CalcUniToUtf8(str) + 1;
436 	data = ZeroMalloc(size);
437 
438 	UniToUtf8(data, size, str);
439 
440 	WriteBuf(b, data, size - 1);
441 
442 	Free(data);
443 }
444 
445 // Creating a shared buffer
NewSharedBuffer(void * data,UINT size)446 SHARED_BUFFER *NewSharedBuffer(void *data, UINT size)
447 {
448 	SHARED_BUFFER *b = ZeroMalloc(sizeof(SHARED_BUFFER));
449 
450 	b->Ref = NewRef();
451 	b->Data = ZeroMalloc(size);
452 	b->Size = size;
453 
454 	if (data != NULL)
455 	{
456 		Copy(b->Data, data, size);
457 	}
458 
459 	return b;
460 }
461 
462 // Release of the shared buffer
ReleaseSharedBuffer(SHARED_BUFFER * b)463 void ReleaseSharedBuffer(SHARED_BUFFER *b)
464 {
465 	// Validate arguments
466 	if (b == NULL)
467 	{
468 		return;
469 	}
470 
471 	if (Release(b->Ref) == 0)
472 	{
473 		CleanupSharedBuffer(b);
474 	}
475 }
CleanupSharedBuffer(SHARED_BUFFER * b)476 void CleanupSharedBuffer(SHARED_BUFFER *b)
477 {
478 	// Validate arguments
479 	if (b == NULL)
480 	{
481 		return;
482 	}
483 
484 	Free(b->Data);
485 
486 	Free(b);
487 }
488 
489 // Calculation of a ^ b (a to the b-th power)
Power(UINT a,UINT b)490 UINT Power(UINT a, UINT b)
491 {
492 	UINT ret, i;
493 	if (a == 0)
494 	{
495 		return 0;
496 	}
497 	if (b == 0)
498 	{
499 		return 1;
500 	}
501 
502 	ret = 1;
503 	for (i = 0;i < b;i++)
504 	{
505 		ret *= a;
506 	}
507 
508 	return ret;
509 }
510 
511 // Search in the binary
SearchBin(void * data,UINT data_start,UINT data_size,void * key,UINT key_size)512 UINT SearchBin(void *data, UINT data_start, UINT data_size, void *key, UINT key_size)
513 {
514 	UINT i;
515 	// Validate arguments
516 	if (data == NULL || key == NULL || key_size == 0 || data_size == 0 ||
517 		(data_start >= data_size) || (data_start + key_size > data_size))
518 	{
519 		return INFINITE;
520 	}
521 
522 	for (i = data_start;i < (data_size - key_size + 1);i++)
523 	{
524 		UCHAR *p = ((UCHAR *)data) + i;
525 
526 		if (Cmp(p, key, key_size) == 0)
527 		{
528 			return i;
529 		}
530 	}
531 
532 	return INFINITE;
533 }
534 
535 // Crash immediately
CrashNow()536 void CrashNow()
537 {
538 	while (true)
539 	{
540 		UINT r = Rand32();
541 		UCHAR *c = (UCHAR *)r;
542 
543 		*c = Rand8();
544 	}
545 }
546 
547 // Convert the buffer to candidate
BufToCandidate(BUF * b)548 LIST *BufToCandidate(BUF *b)
549 {
550 	LIST *o;
551 	UINT i;
552 	UINT num;
553 	// Validate arguments
554 	if (b == NULL)
555 	{
556 		return NULL;
557 	}
558 
559 	num = ReadBufInt(b);
560 	o = NewCandidateList();
561 
562 	for (i = 0;i < num;i++)
563 	{
564 		CANDIDATE *c;
565 		wchar_t *s;
566 		UINT64 sec64;
567 		UINT len, size;
568 		sec64 = ReadBufInt64(b);
569 		len = ReadBufInt(b);
570 		if (len >= 65536)
571 		{
572 			break;
573 		}
574 		size = (len + 1) * 2;
575 		s = ZeroMalloc(size);
576 		if (ReadBuf(b, s, size) != size)
577 		{
578 			Free(s);
579 			break;
580 		}
581 		else
582 		{
583 			c = ZeroMalloc(sizeof(CANDIDATE));
584 			c->LastSelectedTime = sec64;
585 			c->Str = s;
586 			Add(o, c);
587 		}
588 	}
589 
590 	Sort(o);
591 	return o;
592 }
593 
594 // Convert the candidate to buffer
CandidateToBuf(LIST * o)595 BUF *CandidateToBuf(LIST *o)
596 {
597 	BUF *b;
598 	UINT i;
599 	// Validate arguments
600 	if (o == NULL)
601 	{
602 		return NULL;
603 	}
604 
605 	b = NewBuf();
606 	WriteBufInt(b, LIST_NUM(o));
607 	for (i = 0;i < LIST_NUM(o);i++)
608 	{
609 		CANDIDATE *c = LIST_DATA(o, i);
610 		WriteBufInt64(b, c->LastSelectedTime);
611 		WriteBufInt(b, UniStrLen(c->Str));
612 		WriteBuf(b, c->Str, UniStrSize(c->Str));
613 	}
614 
615 	SeekBuf(b, 0, 0);
616 
617 	return b;
618 }
619 
620 // Adding a candidate
AddCandidate(LIST * o,wchar_t * str,UINT num_max)621 void AddCandidate(LIST *o, wchar_t *str, UINT num_max)
622 {
623 	UINT i;
624 	bool exists;
625 	// Validate arguments
626 	if (o == NULL || str == NULL)
627 	{
628 		return;
629 	}
630 	if (num_max == 0)
631 	{
632 		num_max = 0x7fffffff;
633 	}
634 
635 	// String copy
636 	str = UniCopyStr(str);
637 	UniTrim(str);
638 
639 	exists = false;
640 	for (i = 0;i < LIST_NUM(o);i++)
641 	{
642 		CANDIDATE *c = LIST_DATA(o, i);
643 		if (UniStrCmpi(c->Str, str) == 0)
644 		{
645 			// Update the time that an existing entry have been found
646 			c->LastSelectedTime = SystemTime64();
647 			exists = true;
648 			break;
649 		}
650 	}
651 
652 	if (exists == false)
653 	{
654 		// Insert new
655 		CANDIDATE *c = ZeroMalloc(sizeof(CANDIDATE));
656 		c->LastSelectedTime = SystemTime64();
657 		c->Str = UniCopyStr(str);
658 		Insert(o, c);
659 	}
660 
661 	// Release the string
662 	Free(str);
663 
664 	// Check the current number of candidates.
665 	// If it is more than num_max, remove from an oldest candidate sequentially.
666 	if (LIST_NUM(o) > num_max)
667 	{
668 		while (LIST_NUM(o) > num_max)
669 		{
670 			UINT index = LIST_NUM(o) - 1;
671 			CANDIDATE *c = LIST_DATA(o, index);
672 			Delete(o, c);
673 			Free(c->Str);
674 			Free(c);
675 		}
676 	}
677 }
678 
679 // Comparison of candidates
CompareCandidate(void * p1,void * p2)680 int CompareCandidate(void *p1, void *p2)
681 {
682 	CANDIDATE *c1, *c2;
683 	if (p1 == NULL || p2 == NULL)
684 	{
685 		return 0;
686 	}
687 	c1 = *(CANDIDATE **)p1;
688 	c2 = *(CANDIDATE **)p2;
689 	if (c1 == NULL || c2 == NULL)
690 	{
691 		return 0;
692 	}
693 	if (c1->LastSelectedTime > c2->LastSelectedTime)
694 	{
695 		return -1;
696 	}
697 	else if (c1->LastSelectedTime < c2->LastSelectedTime)
698 	{
699 		return 1;
700 	}
701 	else
702 	{
703 		return UniStrCmpi(c1->Str, c2->Str);
704 	}
705 }
706 
707 // Release of the candidate list
FreeCandidateList(LIST * o)708 void FreeCandidateList(LIST *o)
709 {
710 	UINT i;
711 	// Validate arguments
712 	if (o == NULL)
713 	{
714 		return;
715 	}
716 
717 	for (i = 0;i < LIST_NUM(o);i++)
718 	{
719 		CANDIDATE *c = LIST_DATA(o, i);
720 		Free(c->Str);
721 		Free(c);
722 	}
723 
724 	ReleaseList(o);
725 }
726 
727 // Creating a new candidate list
NewCandidateList()728 LIST *NewCandidateList()
729 {
730 	return NewList(CompareCandidate);
731 }
732 
733 // Examine whether the specified address points all-zero area
IsZero(void * data,UINT size)734 bool IsZero(void *data, UINT size)
735 {
736 	UINT i;
737 	UCHAR *c = (UCHAR *)data;
738 	// Validate arguments
739 	if (data == NULL || size == 0)
740 	{
741 		return true;
742 	}
743 
744 	for (i = 0;i < size;i++)
745 	{
746 		if (c[i] != 0)
747 		{
748 			return false;
749 		}
750 	}
751 
752 	return true;
753 }
754 
755 // Expand the data
Uncompress(void * dst,UINT dst_size,void * src,UINT src_size)756 UINT Uncompress(void *dst, UINT dst_size, void *src, UINT src_size)
757 {
758 	unsigned long dst_size_long = dst_size;
759 	// Validate arguments
760 	if (dst == NULL || dst_size_long == 0 || src == NULL)
761 	{
762 		return 0;
763 	}
764 
765 	if (uncompress(dst, &dst_size_long, src, src_size) != Z_OK)
766 	{
767 		return 0;
768 	}
769 
770 	return (UINT)dst_size_long;
771 }
UncompressBuf(BUF * src_buf)772 BUF *UncompressBuf(BUF *src_buf)
773 {
774 	UINT dst_size, dst_size2;
775 	UCHAR *dst;
776 	BUF *b;
777 	// Validate arguments
778 	if (src_buf == NULL)
779 	{
780 		return NULL;
781 	}
782 
783 	SeekBuf(src_buf, 0, 0);
784 	dst_size = ReadBufInt(src_buf);
785 
786 	dst = Malloc(dst_size);
787 
788 	dst_size2 = Uncompress(dst, dst_size, ((UCHAR *)src_buf->Buf) + sizeof(UINT), src_buf->Size - sizeof(UINT));
789 
790 	b = NewBuf();
791 	WriteBuf(b, dst, dst_size2);
792 	Free(dst);
793 
794 	return b;
795 }
796 
797 // Compress the data
Compress(void * dst,UINT dst_size,void * src,UINT src_size)798 UINT Compress(void *dst, UINT dst_size, void *src, UINT src_size)
799 {
800 	return CompressEx(dst, dst_size, src, src_size, Z_DEFAULT_COMPRESSION);
801 }
CompressBuf(BUF * src_buf)802 BUF *CompressBuf(BUF *src_buf)
803 {
804 	UINT dst_size;
805 	UCHAR *dst_buf;
806 	BUF *b;
807 	// Validate arguments
808 	if (src_buf == NULL)
809 	{
810 		return NULL;
811 	}
812 
813 	dst_size = CalcCompress(src_buf->Size);
814 	dst_buf = Malloc(dst_size);
815 
816 	dst_size = Compress(dst_buf, dst_size, src_buf->Buf, src_buf->Size);
817 
818 	if (dst_size == 0)
819 	{
820 		Free(dst_buf);
821 		return NULL;
822 	}
823 
824 	b = NewBuf();
825 	WriteBufInt(b, src_buf->Size);
826 	WriteBuf(b, dst_buf, dst_size);
827 
828 	Free(dst_buf);
829 
830 	return b;
831 }
832 
833 // Compress the data with options
CompressEx(void * dst,UINT dst_size,void * src,UINT src_size,UINT level)834 UINT CompressEx(void *dst, UINT dst_size, void *src, UINT src_size, UINT level)
835 {
836 	unsigned long dst_size_long = dst_size;
837 	// Validate arguments
838 	if (dst == NULL || dst_size_long == 0 || src == NULL)
839 	{
840 		return 0;
841 	}
842 
843 	if (compress2(dst, &dst_size_long, src, src_size, (int)level) != Z_OK)
844 	{
845 		return 0;
846 	}
847 
848 	return dst_size_long;
849 }
850 
851 // Get the maximum size of compressed data from data of src_size
CalcCompress(UINT src_size)852 UINT CalcCompress(UINT src_size)
853 {
854 	return src_size * 2 + 256;
855 }
856 
857 // Creating a Stack
NewSk()858 SK *NewSk()
859 {
860 	return NewSkEx(false);
861 }
NewSkEx(bool no_compact)862 SK *NewSkEx(bool no_compact)
863 {
864 	SK *s;
865 
866 	s = Malloc(sizeof(SK));
867 	s->lock = NewLock();
868 	s->ref = NewRef();
869 	s->num_item = 0;
870 	s->num_reserved = INIT_NUM_RESERVED;
871 	s->p = Malloc(sizeof(void *) * s->num_reserved);
872 	s->no_compact = no_compact;
873 
874 	// KS
875 	KS_INC(KS_NEWSK_COUNT);
876 
877 	return s;
878 }
879 
880 // Release of the stack
ReleaseSk(SK * s)881 void ReleaseSk(SK *s)
882 {
883 	// Validate arguments
884 	if (s == NULL)
885 	{
886 		return;
887 	}
888 
889 	if (Release(s->ref) == 0)
890 	{
891 		CleanupSk(s);
892 	}
893 }
894 
895 // Clean up the stack
CleanupSk(SK * s)896 void CleanupSk(SK *s)
897 {
898 	// Validate arguments
899 	if (s == NULL)
900 	{
901 		return;
902 	}
903 
904 	// Memory release
905 	Free(s->p);
906 	DeleteLock(s->lock);
907 	Free(s);
908 
909 	// KS
910 	KS_INC(KS_FREESK_COUNT);
911 }
912 
913 // Lock of the stack
LockSk(SK * s)914 void LockSk(SK *s)
915 {
916 	// Validate arguments
917 	if (s == NULL)
918 	{
919 		return;
920 	}
921 
922 	Lock(s->lock);
923 }
924 
925 // Unlock the stack
UnlockSk(SK * s)926 void UnlockSk(SK *s)
927 {
928 	// Validate arguments
929 	if (s == NULL)
930 	{
931 		return;
932 	}
933 
934 	Unlock(s->lock);
935 }
936 
937 // Push to the stack
Push(SK * s,void * p)938 void Push(SK *s, void *p)
939 {
940 	UINT i;
941 	// Validate arguments
942 	if (s == NULL || p == NULL)
943 	{
944 		return;
945 	}
946 
947 	i = s->num_item;
948 	s->num_item++;
949 
950 	// Size expansion
951 	if (s->num_item > s->num_reserved)
952 	{
953 		s->num_reserved = s->num_reserved * 2;
954 		s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
955 	}
956 	s->p[i] = p;
957 
958 	// KS
959 	KS_INC(KS_PUSH_COUNT);
960 }
961 
962 // Pop from the stack
Pop(SK * s)963 void *Pop(SK *s)
964 {
965 	void *ret;
966 	// Validate arguments
967 	if (s == NULL)
968 	{
969 		return NULL;
970 	}
971 	if (s->num_item == 0)
972 	{
973 		return NULL;
974 	}
975 	ret = s->p[s->num_item - 1];
976 	s->num_item--;
977 
978 	// Size reduction
979 	if (s->no_compact == false)
980 	{
981 		// Not to shrink when no_compact is true
982 		if ((s->num_item * 2) <= s->num_reserved)
983 		{
984 			if (s->num_reserved >= (INIT_NUM_RESERVED * 2))
985 			{
986 				s->num_reserved = s->num_reserved / 2;
987 				s->p = ReAlloc(s->p, sizeof(void *) * s->num_reserved);
988 			}
989 		}
990 	}
991 
992 	// KS
993 	KS_INC(KS_POP_COUNT);
994 
995 	return ret;
996 }
997 
998 // Get the number of queued items
GetQueueNum(QUEUE * q)999 UINT GetQueueNum(QUEUE *q)
1000 {
1001 	// Validate arguments
1002 	if (q == NULL)
1003 	{
1004 		return 0;
1005 	}
1006 
1007 	return q->num_item;
1008 }
1009 
1010 // Get one
GetNext(QUEUE * q)1011 void *GetNext(QUEUE *q)
1012 {
1013 	void *p = NULL;
1014 	// Validate arguments
1015 	if (q == NULL)
1016 	{
1017 		return NULL;
1018 	}
1019 
1020 	if (q->num_item == 0)
1021 	{
1022 		// No items
1023 		return NULL;
1024 	}
1025 
1026 	// Read from the FIFO
1027 	ReadFifo(q->fifo, &p, sizeof(void *));
1028 	q->num_item--;
1029 
1030 	// KS
1031 	KS_INC(KS_GETNEXT_COUNT);
1032 
1033 	return p;
1034 }
1035 
1036 // Get one item from the queue (locking)
GetNextWithLock(QUEUE * q)1037 void *GetNextWithLock(QUEUE *q)
1038 {
1039 	void *p;
1040 	// Validate arguments
1041 	if (q == NULL)
1042 	{
1043 		return NULL;
1044 	}
1045 
1046 	LockQueue(q);
1047 	{
1048 		p = GetNext(q);
1049 	}
1050 	UnlockQueue(q);
1051 
1052 	return p;
1053 }
1054 
1055 // Insert the int type in the queue
InsertQueueInt(QUEUE * q,UINT value)1056 void InsertQueueInt(QUEUE *q, UINT value)
1057 {
1058 	UINT *p;
1059 	// Validate arguments
1060 	if (q == NULL)
1061 	{
1062 		return;
1063 	}
1064 
1065 	p = Clone(&value, sizeof(UINT));
1066 
1067 	InsertQueue(q, p);
1068 }
1069 
1070 // Insert to the queue
InsertQueue(QUEUE * q,void * p)1071 void InsertQueue(QUEUE *q, void *p)
1072 {
1073 	// Validate arguments
1074 	if (q == NULL || p == NULL)
1075 	{
1076 		return;
1077 	}
1078 
1079 	// Write to the FIFO
1080 	WriteFifo(q->fifo, &p, sizeof(void *));
1081 
1082 	q->num_item++;
1083 
1084 	/*{
1085 		static UINT max_num_item;
1086 		static UINT64 next_tick = 0;
1087 		UINT64 now = Tick64();
1088 
1089 		max_num_item = MAX(q->num_item, max_num_item);
1090 
1091 		if (next_tick == 0 || next_tick <= now)
1092 		{
1093 			next_tick = now + (UINT64)1000;
1094 
1095 			printf("max_queue = %u\n", max_num_item);
1096 		}
1097 	}*/
1098 
1099 	// KS
1100 	KS_INC(KS_INSERT_QUEUE_COUNT);
1101 }
1102 
1103 // Insert to the queue (locking)
InsertQueueWithLock(QUEUE * q,void * p)1104 void InsertQueueWithLock(QUEUE *q, void *p)
1105 {
1106 	// Validate arguments
1107 	if (q == NULL || p == NULL)
1108 	{
1109 		return;
1110 	}
1111 
1112 	LockQueue(q);
1113 	{
1114 		InsertQueue(q, p);
1115 	}
1116 	UnlockQueue(q);
1117 }
1118 
1119 // Lock the queue
LockQueue(QUEUE * q)1120 void LockQueue(QUEUE *q)
1121 {
1122 	// Validate arguments
1123 	if (q == NULL)
1124 	{
1125 		return;
1126 	}
1127 
1128 	Lock(q->lock);
1129 }
1130 
1131 // Unlock the queue
UnlockQueue(QUEUE * q)1132 void UnlockQueue(QUEUE *q)
1133 {
1134 	// Validate arguments
1135 	if (q == NULL)
1136 	{
1137 		return;
1138 	}
1139 
1140 	Unlock(q->lock);
1141 }
1142 
1143 // Release of the queue
ReleaseQueue(QUEUE * q)1144 void ReleaseQueue(QUEUE *q)
1145 {
1146 	// Validate arguments
1147 	if (q == NULL)
1148 	{
1149 		return;
1150 	}
1151 
1152 	if (q->ref == NULL || Release(q->ref) == 0)
1153 	{
1154 		CleanupQueue(q);
1155 	}
1156 }
1157 
1158 // Clean-up the queue
CleanupQueue(QUEUE * q)1159 void CleanupQueue(QUEUE *q)
1160 {
1161 	// Validate arguments
1162 	if (q == NULL)
1163 	{
1164 		return;
1165 	}
1166 
1167 	// Memory release
1168 	ReleaseFifo(q->fifo);
1169 	DeleteLock(q->lock);
1170 	Free(q);
1171 
1172 	// KS
1173 	KS_INC(KS_FREEQUEUE_COUNT);
1174 }
1175 
1176 // Creating a Queue
NewQueue()1177 QUEUE *NewQueue()
1178 {
1179 	QUEUE *q;
1180 
1181 	q = ZeroMalloc(sizeof(QUEUE));
1182 	q->lock = NewLock();
1183 	q->ref = NewRef();
1184 	q->num_item = 0;
1185 	q->fifo = NewFifo();
1186 
1187 	// KS
1188 	KS_INC(KS_NEWQUEUE_COUNT);
1189 
1190 	return q;
1191 }
NewQueueFast()1192 QUEUE *NewQueueFast()
1193 {
1194 	QUEUE *q;
1195 
1196 	q = ZeroMalloc(sizeof(QUEUE));
1197 	q->lock = NULL;
1198 	q->ref = NULL;
1199 	q->num_item = 0;
1200 	q->fifo = NewFifoFast();
1201 
1202 	// KS
1203 	KS_INC(KS_NEWQUEUE_COUNT);
1204 
1205 	return q;
1206 }
1207 
1208 // Clone the list
CloneList(LIST * o)1209 LIST *CloneList(LIST *o)
1210 {
1211 	LIST *n = NewList(o->cmp);
1212 
1213 	// Memory reallocation
1214 	Free(n->p);
1215 	n->p = ToArray(o);
1216 	n->num_item = n->num_reserved = LIST_NUM(o);
1217 	n->sorted = o->sorted;
1218 
1219 	return n;
1220 }
1221 
1222 // Copy the list to an array
CopyToArray(LIST * o,void * p)1223 void CopyToArray(LIST *o, void *p)
1224 {
1225 	// Validate arguments
1226 	if (o == NULL || p == NULL)
1227 	{
1228 		return;
1229 	}
1230 
1231 	// KS
1232 	KS_INC(KS_TOARRAY_COUNT);
1233 
1234 	Copy(p, o->p, sizeof(void *) * o->num_item);
1235 }
1236 
1237 // Arrange the list to an array
ToArray(LIST * o)1238 void *ToArray(LIST *o)
1239 {
1240 	return ToArrayEx(o, false);
1241 }
ToArrayEx(LIST * o,bool fast)1242 void *ToArrayEx(LIST *o, bool fast)
1243 {
1244 	void *p;
1245 	// Validate arguments
1246 	if (o == NULL)
1247 	{
1248 		return NULL;
1249 	}
1250 
1251 	// Memory allocation
1252 	if (fast == false)
1253 	{
1254 		p = Malloc(sizeof(void *) * LIST_NUM(o));
1255 	}
1256 	else
1257 	{
1258 		p = MallocFast(sizeof(void *) * LIST_NUM(o));
1259 	}
1260 	// Copy
1261 	CopyToArray(o, p);
1262 
1263 	return p;
1264 }
1265 
1266 // Search in the list
Search(LIST * o,void * target)1267 void *Search(LIST *o, void *target)
1268 {
1269 	void **ret;
1270 	// Validate arguments
1271 	if (o == NULL || target == NULL)
1272 	{
1273 		return NULL;
1274 	}
1275 	if (o->cmp == NULL)
1276 	{
1277 		return NULL;
1278 	}
1279 
1280 	// Check the sort
1281 	if (o->sorted == false)
1282 	{
1283 		// Sort because it is not sorted
1284 		Sort(o);
1285 	}
1286 
1287 	ret = (void **)bsearch(&target, o->p, o->num_item, sizeof(void *),
1288 		(int(*)(const void *, const void *))o->cmp);
1289 
1290 	// KS
1291 	KS_INC(KS_SEARCH_COUNT);
1292 
1293 	if (ret != NULL)
1294 	{
1295 		return *ret;
1296 	}
1297 	else
1298 	{
1299 		return NULL;
1300 	}
1301 }
1302 
1303 // Insert an item to the list
Insert(LIST * o,void * p)1304 void Insert(LIST *o, void *p)
1305 {
1306 	int low, high, middle;
1307 	UINT pos;
1308 	int i;
1309 	// Validate arguments
1310 	if (o == NULL || p == NULL)
1311 	{
1312 		return;
1313 	}
1314 
1315 	if (o->cmp == NULL)
1316 	{
1317 		// adding simply if there is no sort function
1318 		Add(o, p);
1319 		return;
1320 	}
1321 
1322 	// Sort immediately if it is not sorted
1323 	if (o->sorted == false)
1324 	{
1325 		Sort(o);
1326 	}
1327 
1328 	low = 0;
1329 	high = LIST_NUM(o) - 1;
1330 
1331 	pos = INFINITE;
1332 
1333 	while (low <= high)
1334 	{
1335 		int ret;
1336 
1337 		middle = (low + high) / 2;
1338 		ret = o->cmp(&(o->p[middle]), &p);
1339 
1340 		if (ret == 0)
1341 		{
1342 			pos = middle;
1343 			break;
1344 		}
1345 		else if (ret > 0)
1346 		{
1347 			high = middle - 1;
1348 		}
1349 		else
1350 		{
1351 			low = middle + 1;
1352 		}
1353 	}
1354 
1355 	if (pos == INFINITE)
1356 	{
1357 		pos = low;
1358 	}
1359 
1360 	o->num_item++;
1361 	if (o->num_item > o->num_reserved)
1362 	{
1363 		o->num_reserved *= 2;
1364 		o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
1365 	}
1366 
1367 	if (LIST_NUM(o) >= 2)
1368 	{
1369 		for (i = (LIST_NUM(o) - 2);i >= (int)pos;i--)
1370 		{
1371 			o->p[i + 1] = o->p[i];
1372 		}
1373 	}
1374 
1375 	o->p[pos] = p;
1376 
1377 	// KS
1378 	KS_INC(KS_INSERT_COUNT);
1379 }
1380 
1381 // Sort the list
Sort(LIST * o)1382 void Sort(LIST *o)
1383 {
1384 	// Validate arguments
1385 	if (o == NULL || o->cmp == NULL)
1386 	{
1387 		return;
1388 	}
1389 
1390 	qsort(o->p, o->num_item, sizeof(void *), (int(*)(const void *, const void *))o->cmp);
1391 	o->sorted = true;
1392 
1393 	// KS
1394 	KS_INC(KS_SORT_COUNT);
1395 }
1396 
1397 // Replace the pointer in the list
ReplaceListPointer(LIST * o,void * oldptr,void * newptr)1398 bool ReplaceListPointer(LIST *o, void *oldptr, void *newptr)
1399 {
1400 	UINT i;
1401 	// Validate arguments
1402 	if (o == NULL || oldptr == NULL || newptr == NULL)
1403 	{
1404 		return false;
1405 	}
1406 
1407 	for (i = 0;i < LIST_NUM(o);i++)
1408 	{
1409 		void *p = LIST_DATA(o, i);
1410 
1411 		if (p == oldptr)
1412 		{
1413 			o->p[i] = newptr;
1414 			return true;
1415 		}
1416 	}
1417 
1418 	return false;
1419 }
1420 
1421 // New string list
NewStrList()1422 LIST *NewStrList()
1423 {
1424 	return NewListFast(CompareStr);
1425 }
1426 
1427 // Release string list
ReleaseStrList(LIST * o)1428 void ReleaseStrList(LIST *o)
1429 {
1430 	UINT i;
1431 	if (o == NULL)
1432 	{
1433 		return;
1434 	}
1435 
1436 	for (i = 0;i < LIST_NUM(o);i++)
1437 	{
1438 		char *s = LIST_DATA(o, i);
1439 		Free(s);
1440 	}
1441 
1442 	ReleaseList(o);
1443 }
1444 
1445 // Add a string distinct to the string list
AddStrToStrListDistinct(LIST * o,char * str)1446 bool AddStrToStrListDistinct(LIST *o, char *str)
1447 {
1448 	if (o == NULL || str == NULL)
1449 	{
1450 		return false;
1451 	}
1452 
1453 	if (IsInListStr(o, str) == false)
1454 	{
1455 		Add(o, CopyStr(str));
1456 
1457 		return true;
1458 	}
1459 
1460 	return false;
1461 }
1462 
1463 // Examine whether a string items are present in the list
IsInListStr(LIST * o,char * str)1464 bool IsInListStr(LIST *o, char *str)
1465 {
1466 	UINT i;
1467 	// Validate arguments
1468 	if (o == NULL || str == NULL)
1469 	{
1470 		return false;
1471 	}
1472 
1473 	for (i = 0;i < LIST_NUM(o);i++)
1474 	{
1475 		char *s = LIST_DATA(o, i);
1476 
1477 		if (StrCmpi(s, str) == 0)
1478 		{
1479 			return true;
1480 		}
1481 	}
1482 
1483 	return false;
1484 }
1485 
IsInListUniStr(LIST * o,wchar_t * str)1486 bool IsInListUniStr(LIST *o, wchar_t *str)
1487 {
1488 	UINT i;
1489 	// Validate arguments
1490 	if (o == NULL || str == NULL)
1491 	{
1492 		return false;
1493 	}
1494 
1495 	for (i = 0; i < LIST_NUM(o); i++)
1496 	{
1497 		wchar_t *s = LIST_DATA(o, i);
1498 
1499 		if (UniStrCmpi(s, str) == 0)
1500 		{
1501 			return true;
1502 		}
1503 	}
1504 
1505 	return false;
1506 }
1507 
1508 // Get the pointer by scanning by UINT pointer in the list
ListKeyToPointer(LIST * o,UINT key)1509 void *ListKeyToPointer(LIST *o, UINT key)
1510 {
1511 	UINT i;
1512 	// Validate arguments
1513 	if (o == NULL || key == 0)
1514 	{
1515 		return NULL;
1516 	}
1517 
1518 	for (i = 0;i < LIST_NUM(o);i++)
1519 	{
1520 		void *p = LIST_DATA(o, i);
1521 
1522 		if (POINTER_TO_KEY(p) == key)
1523 		{
1524 			return p;
1525 		}
1526 	}
1527 
1528 	return NULL;
1529 }
1530 
1531 // Examine whether the key is present in the list
IsInListKey(LIST * o,UINT key)1532 bool IsInListKey(LIST *o, UINT key)
1533 {
1534 	void *p;
1535 	// Validate arguments
1536 	if (o == NULL || key == 0)
1537 	{
1538 		return false;
1539 	}
1540 
1541 	p = ListKeyToPointer(o, key);
1542 	if (p == NULL)
1543 	{
1544 		return false;
1545 	}
1546 
1547 	return true;
1548 }
1549 
1550 // Examine whether the item exists in the list
IsInList(LIST * o,void * p)1551 bool IsInList(LIST *o, void *p)
1552 {
1553 	UINT i;
1554 	// Validate arguments
1555 	if (o == NULL || p == NULL)
1556 	{
1557 		return false;
1558 	}
1559 
1560 	for (i = 0;i < LIST_NUM(o);i++)
1561 	{
1562 		void *q = LIST_DATA(o, i);
1563 		if (p == q)
1564 		{
1565 			return true;
1566 		}
1567 	}
1568 
1569 	return false;
1570 }
1571 
1572 // Add an element to the list (Don't add if it already exists)
AddDistinct(LIST * o,void * p)1573 void AddDistinct(LIST *o, void *p)
1574 {
1575 	// Validate arguments
1576 	if (o == NULL || p == NULL)
1577 	{
1578 		return;
1579 	}
1580 
1581 	if (IsInList(o, p))
1582 	{
1583 		return;
1584 	}
1585 
1586 	Add(o, p);
1587 }
1588 
1589 // Add an element to the list
Add(LIST * o,void * p)1590 void Add(LIST *o, void *p)
1591 {
1592 	UINT i;
1593 	// Validate arguments
1594 	if (o == NULL || p == NULL)
1595 	{
1596 		return;
1597 	}
1598 
1599 	i = o->num_item;
1600 	o->num_item++;
1601 
1602 	if (o->num_item > o->num_reserved)
1603 	{
1604 		o->num_reserved = o->num_reserved * 2;
1605 		o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
1606 	}
1607 
1608 	o->p[i] = p;
1609 	o->sorted = false;
1610 
1611 	// KS
1612 	KS_INC(KS_INSERT_COUNT);
1613 }
1614 
1615 // Delete the element from the list
Delete(LIST * o,void * p)1616 bool Delete(LIST *o, void *p)
1617 {
1618 	UINT i, n;
1619 	// Validate arguments
1620 	if (o == NULL || p == NULL)
1621 	{
1622 		return false;
1623 	}
1624 
1625 	for (i = 0;i < o->num_item;i++)
1626 	{
1627 		if (o->p[i] == p)
1628 		{
1629 			break;
1630 		}
1631 	}
1632 	if (i == o->num_item)
1633 	{
1634 		return false;
1635 	}
1636 
1637 	n = i;
1638 	for (i = n;i < (o->num_item - 1);i++)
1639 	{
1640 		o->p[i] = o->p[i + 1];
1641 	}
1642 	o->num_item--;
1643 	if ((o->num_item * 2) <= o->num_reserved)
1644 	{
1645 		if (o->num_reserved > (INIT_NUM_RESERVED * 2))
1646 		{
1647 			o->num_reserved = o->num_reserved / 2;
1648 			o->p = ReAlloc(o->p, sizeof(void *) * o->num_reserved);
1649 		}
1650 	}
1651 
1652 	// KS
1653 	KS_INC(KS_DELETE_COUNT);
1654 
1655 	return true;
1656 }
1657 
1658 // Delete all elements from the list
DeleteAll(LIST * o)1659 void DeleteAll(LIST *o)
1660 {
1661 	// Validate arguments
1662 	if (o == NULL)
1663 	{
1664 		return;
1665 	}
1666 
1667 	o->num_item = 0;
1668 	o->num_reserved = INIT_NUM_RESERVED;
1669 	o->p = ReAlloc(o->p, sizeof(void *) * INIT_NUM_RESERVED);
1670 }
1671 
1672 // Lock the list
LockList(LIST * o)1673 void LockList(LIST *o)
1674 {
1675 	// Validate arguments
1676 	if (o == NULL)
1677 	{
1678 		return;
1679 	}
1680 
1681 	Lock(o->lock);
1682 }
1683 
1684 // Unlock the list
UnlockList(LIST * o)1685 void UnlockList(LIST *o)
1686 {
1687 	// Validate arguments
1688 	if (o == NULL)
1689 	{
1690 		return;
1691 	}
1692 
1693 	Unlock(o->lock);
1694 }
1695 
1696 // Release the list
ReleaseList(LIST * o)1697 void ReleaseList(LIST *o)
1698 {
1699 	// Validate arguments
1700 	if (o == NULL)
1701 	{
1702 		return;
1703 	}
1704 
1705 	if (o->ref == NULL || Release(o->ref) == 0)
1706 	{
1707 		CleanupList(o);
1708 	}
1709 }
1710 
1711 // Clean up the list
CleanupList(LIST * o)1712 void CleanupList(LIST *o)
1713 {
1714 	// Validate arguments
1715 	if (o == NULL)
1716 	{
1717 		return;
1718 	}
1719 
1720 	Free(o->p);
1721 	if (o->lock != NULL)
1722 	{
1723 		DeleteLock(o->lock);
1724 	}
1725 	Free(o);
1726 
1727 	// KS
1728 	KS_INC(KS_FREELIST_COUNT);
1729 }
1730 
1731 // Check whether the specified number is already in the list
IsIntInList(LIST * o,UINT i)1732 bool IsIntInList(LIST *o, UINT i)
1733 {
1734 	UINT j;
1735 	// Validate arguments
1736 	if (o == NULL)
1737 	{
1738 		return false;
1739 	}
1740 
1741 	for (j = 0;j < LIST_NUM(o);j++)
1742 	{
1743 		UINT *p = LIST_DATA(o, j);
1744 
1745 		if (*p == i)
1746 		{
1747 			return true;
1748 		}
1749 	}
1750 
1751 	return false;
1752 }
IsInt64InList(LIST * o,UINT64 i)1753 bool IsInt64InList(LIST *o, UINT64 i)
1754 {
1755 	UINT j;
1756 	// Validate arguments
1757 	if (o == NULL)
1758 	{
1759 		return false;
1760 	}
1761 
1762 	for (j = 0;j < LIST_NUM(o);j++)
1763 	{
1764 		UINT64 *p = LIST_DATA(o, j);
1765 
1766 		if (*p == i)
1767 		{
1768 			return true;
1769 		}
1770 	}
1771 
1772 	return false;
1773 }
1774 
1775 // Release the integer list
ReleaseIntList(LIST * o)1776 void ReleaseIntList(LIST *o)
1777 {
1778 	UINT i;
1779 	// Validate arguments
1780 	if (o == NULL)
1781 	{
1782 		return;
1783 	}
1784 
1785 	for (i = 0;i < LIST_NUM(o);i++)
1786 	{
1787 		UINT *p = LIST_DATA(o, i);
1788 
1789 		Free(p);
1790 	}
1791 
1792 	ReleaseList(o);
1793 }
ReleaseInt64List(LIST * o)1794 void ReleaseInt64List(LIST *o)
1795 {
1796 	UINT i;
1797 	// Validate arguments
1798 	if (o == NULL)
1799 	{
1800 		return;
1801 	}
1802 
1803 	for (i = 0;i < LIST_NUM(o);i++)
1804 	{
1805 		UINT64 *p = LIST_DATA(o, i);
1806 
1807 		Free(p);
1808 	}
1809 
1810 	ReleaseList(o);
1811 }
1812 
1813 // Delete an integer from list
DelInt(LIST * o,UINT i)1814 void DelInt(LIST *o, UINT i)
1815 {
1816 	LIST *o2 = NULL;
1817 	UINT j;
1818 	// Validate arguments
1819 	if (o == NULL)
1820 	{
1821 		return;
1822 	}
1823 
1824 	for (j = 0;j < LIST_NUM(o);j++)
1825 	{
1826 		UINT *p = LIST_DATA(o, j);
1827 
1828 		if (*p == i)
1829 		{
1830 			if (o2 == NULL)
1831 			{
1832 				o2 = NewListFast(NULL);
1833 			}
1834 			Add(o2, p);
1835 		}
1836 	}
1837 
1838 	for (j = 0;j < LIST_NUM(o2);j++)
1839 	{
1840 		UINT *p = LIST_DATA(o2, j);
1841 
1842 		Delete(o, p);
1843 
1844 		Free(p);
1845 	}
1846 
1847 	if (o2 != NULL)
1848 	{
1849 		ReleaseList(o2);
1850 	}
1851 }
1852 
1853 // Create a new list of integers
NewIntList(bool sorted)1854 LIST *NewIntList(bool sorted)
1855 {
1856 	LIST *o = NewList(sorted ? CompareInt : NULL);
1857 
1858 	return o;
1859 }
NewInt64List(bool sorted)1860 LIST *NewInt64List(bool sorted)
1861 {
1862 	LIST *o = NewList(sorted ? CompareInt64 : NULL);
1863 
1864 	return o;
1865 }
1866 
1867 // Comparison of items in the list of integers
CompareInt(void * p1,void * p2)1868 int CompareInt(void *p1, void *p2)
1869 {
1870 	UINT *v1, *v2;
1871 	if (p1 == NULL || p2 == NULL)
1872 	{
1873 		return 0;
1874 	}
1875 
1876 	v1 = *((UINT **)p1);
1877 	v2 = *((UINT **)p2);
1878 	if (v1 == NULL || v2 == NULL)
1879 	{
1880 		return 0;
1881 	}
1882 
1883 	return COMPARE_RET(*v1, *v2);
1884 }
CompareInt64(void * p1,void * p2)1885 int CompareInt64(void *p1, void *p2)
1886 {
1887 	UINT64 *v1, *v2;
1888 	if (p1 == NULL || p2 == NULL)
1889 	{
1890 		return 0;
1891 	}
1892 
1893 	v1 = *((UINT64 **)p1);
1894 	v2 = *((UINT64 **)p2);
1895 	if (v1 == NULL || v2 == NULL)
1896 	{
1897 		return 0;
1898 	}
1899 
1900 	return COMPARE_RET(*v1, *v2);
1901 }
1902 
1903 // Add an integer to the list
AddInt(LIST * o,UINT i)1904 void AddInt(LIST *o, UINT i)
1905 {
1906 	// Validate arguments
1907 	if (o == NULL)
1908 	{
1909 		return;
1910 	}
1911 
1912 	Add(o, Clone(&i, sizeof(UINT)));
1913 }
AddInt64(LIST * o,UINT64 i)1914 void AddInt64(LIST *o, UINT64 i)
1915 {
1916 	// Validate arguments
1917 	if (o == NULL)
1918 	{
1919 		return;
1920 	}
1921 
1922 	Add(o, Clone(&i, sizeof(UINT64)));
1923 }
InsertInt(LIST * o,UINT i)1924 void InsertInt(LIST *o, UINT i)
1925 {
1926 	// Validate arguments
1927 	if (o == NULL)
1928 	{
1929 		return;
1930 	}
1931 
1932 	Insert(o, Clone(&i, sizeof(UINT)));
1933 }
1934 
1935 // Add an integer to the list (no duplicates)
AddIntDistinct(LIST * o,UINT i)1936 void AddIntDistinct(LIST *o, UINT i)
1937 {
1938 	// Validate arguments
1939 	if (o == NULL)
1940 	{
1941 		return;
1942 	}
1943 
1944 	if (IsIntInList(o, i) == false)
1945 	{
1946 		AddInt(o, i);
1947 	}
1948 }
AddInt64Distinct(LIST * o,UINT64 i)1949 void AddInt64Distinct(LIST *o, UINT64 i)
1950 {
1951 	// Validate arguments
1952 	if (o == NULL)
1953 	{
1954 		return;
1955 	}
1956 
1957 	if (IsInt64InList(o, i) == false)
1958 	{
1959 		AddInt64(o, i);
1960 	}
1961 }
InsertIntDistinct(LIST * o,UINT i)1962 void InsertIntDistinct(LIST *o, UINT i)
1963 {
1964 	// Validate arguments
1965 	if (o == NULL)
1966 	{
1967 		return;
1968 	}
1969 
1970 	if (IsIntInList(o, i) == false)
1971 	{
1972 		InsertInt(o, i);
1973 	}
1974 }
1975 
1976 // String comparison function (Unicode)
CompareUniStr(void * p1,void * p2)1977 int CompareUniStr(void *p1, void *p2)
1978 {
1979 	wchar_t *s1, *s2;
1980 	if (p1 == NULL || p2 == NULL)
1981 	{
1982 		return 0;
1983 	}
1984 	s1 = *(wchar_t **)p1;
1985 	s2 = *(wchar_t **)p2;
1986 
1987 	return UniStrCmp(s1, s2);
1988 }
1989 
1990 // Insert the string to the list
InsertStr(LIST * o,char * str)1991 bool InsertStr(LIST *o, char *str)
1992 {
1993 	// Validate arguments
1994 	if (o == NULL || str == NULL)
1995 	{
1996 		return false;
1997 	}
1998 
1999 	if (Search(o, str) == NULL)
2000 	{
2001 		Insert(o, str);
2002 
2003 		return true;
2004 	}
2005 
2006 	return false;
2007 }
2008 
2009 // String comparison function
CompareStr(void * p1,void * p2)2010 int CompareStr(void *p1, void *p2)
2011 {
2012 	char *s1, *s2;
2013 	if (p1 == NULL || p2 == NULL)
2014 	{
2015 		return 0;
2016 	}
2017 	s1 = *(char **)p1;
2018 	s2 = *(char **)p2;
2019 
2020 	return StrCmpi(s1, s2);
2021 }
2022 
2023 // Create a list with an item
NewListSingle(void * p)2024 LIST *NewListSingle(void *p)
2025 {
2026 	LIST *o = NewListFast(NULL);
2027 
2028 	Add(o, p);
2029 
2030 	return o;
2031 }
2032 
2033 // Creating a high-speed list (without lock)
NewListFast(COMPARE * cmp)2034 LIST *NewListFast(COMPARE *cmp)
2035 {
2036 	return NewListEx(cmp, true);
2037 }
2038 
2039 // Creating a list
NewList(COMPARE * cmp)2040 LIST *NewList(COMPARE *cmp)
2041 {
2042 	return NewListEx(cmp, false);
2043 }
NewListEx(COMPARE * cmp,bool fast)2044 LIST *NewListEx(COMPARE *cmp, bool fast)
2045 {
2046 	return NewListEx2(cmp, fast, false);
2047 }
NewListEx2(COMPARE * cmp,bool fast,bool fast_malloc)2048 LIST *NewListEx2(COMPARE *cmp, bool fast, bool fast_malloc)
2049 {
2050 	LIST *o;
2051 
2052 	if (fast_malloc == false)
2053 	{
2054 		o = Malloc(sizeof(LIST));
2055 	}
2056 	else
2057 	{
2058 		o = MallocFast(sizeof(LIST));
2059 	}
2060 
2061 	if (fast == false)
2062 	{
2063 		o->lock = NewLock();
2064 		o->ref = NewRef();
2065 	}
2066 	else
2067 	{
2068 		o->lock = NULL;
2069 		o->ref = NULL;
2070 	}
2071 	o->num_item = 0;
2072 	o->num_reserved = INIT_NUM_RESERVED;
2073 	o->Param1 = 0;
2074 
2075 	if (fast_malloc == false)
2076 	{
2077 		o->p = Malloc(sizeof(void *) * o->num_reserved);
2078 	}
2079 	else
2080 	{
2081 		o->p = MallocFast(sizeof(void *) * o->num_reserved);
2082 	}
2083 
2084 	o->cmp = cmp;
2085 	o->sorted = true;
2086 
2087 	// KS
2088 	KS_INC(KS_NEWLIST_COUNT);
2089 
2090 	return o;
2091 }
2092 
2093 // Parses a string by identifying its parts using the specified separators
NewEntryList(char * src,char * key_separator,char * value_separator)2094 LIST *NewEntryList(char *src, char *key_separator, char *value_separator)
2095 {
2096 	LIST *o = NewListFast(NULL);
2097 	TOKEN_LIST *t;
2098 
2099 	t = ParseTokenWithoutNullStr(src, key_separator);
2100 	if (t != NULL)
2101 	{
2102 		UINT i;
2103 
2104 		for (i = 0; i < t->NumTokens; i++)
2105 		{
2106 			char key[MAX_SIZE];
2107 			char value[MAX_SIZE];
2108 			char *line = t->Token[i];
2109 			Trim(line);
2110 
2111 			if (GetKeyAndValue(line, key, sizeof(key), value, sizeof(value), value_separator))
2112 			{
2113 				INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));
2114 
2115 				e->Key = CopyStr(key);
2116 				e->Value = CopyStr(value);
2117 
2118 				Add(o, e);
2119 			}
2120 		}
2121 
2122 		FreeToken(t);
2123 	}
2124 
2125 	return o;
2126 }
2127 
2128 // Checks whether the list contains the specified entry
EntryListHasKey(LIST * o,char * key)2129 bool EntryListHasKey(LIST *o, char *key)
2130 {
2131 	// Validate arguments
2132 	if (o == NULL || key == NULL)
2133 	{
2134 		return false;
2135 	}
2136 
2137 	if (GetIniEntry(o, key) != NULL)
2138 	{
2139 		return true;
2140 	}
2141 
2142 	return false;
2143 }
2144 
2145 // Gets the value of the specified key from the entry list
EntryListStrValue(LIST * o,char * key)2146 char *EntryListStrValue(LIST *o, char *key)
2147 {
2148 	return IniStrValue(o, key);
2149 }
2150 
EntryListIntValue(LIST * o,char * key)2151 UINT EntryListIntValue(LIST *o, char *key)
2152 {
2153 	return IniIntValue(o, key);
2154 }
2155 
2156 // Release the entry list
FreeEntryList(LIST * o)2157 void FreeEntryList(LIST *o)
2158 {
2159 	// Validate arguments
2160 	if (o == NULL)
2161 	{
2162 		return;
2163 	}
2164 
2165 	FreeIni(o);
2166 }
2167 
2168 // Read all data from FIFO
ReadFifoAll(FIFO * f)2169 BUF *ReadFifoAll(FIFO *f)
2170 {
2171 	BUF *buf;
2172 	UCHAR *tmp;
2173 	UINT size;
2174 	if (f == NULL)
2175 	{
2176 		return NewBuf();
2177 	}
2178 
2179 	size = FifoSize(f);
2180 	tmp = Malloc(size);
2181 	ReadFifo(f, tmp, size);
2182 
2183 	buf = MemToBuf(tmp, size);
2184 
2185 	Free(tmp);
2186 
2187 	return buf;
2188 }
2189 
2190 // Read from the FIFO
ReadFifo(FIFO * f,void * p,UINT size)2191 UINT ReadFifo(FIFO *f, void *p, UINT size)
2192 {
2193 	UINT read_size;
2194 	// Validate arguments
2195 	if (f == NULL || size == 0)
2196 	{
2197 		return 0;
2198 	}
2199 
2200 	read_size = MIN(size, f->size);
2201 	if (read_size == 0)
2202 	{
2203 		return 0;
2204 	}
2205 	if (p != NULL)
2206 	{
2207 		Copy(p, (UCHAR *)f->p + f->pos, read_size);
2208 	}
2209 	f->pos += read_size;
2210 	f->size -= read_size;
2211 
2212 	f->total_read_size += (UINT64)read_size;
2213 
2214 	if (f->fixed == false)
2215 	{
2216 		if (f->size == 0)
2217 		{
2218 			f->pos = 0;
2219 		}
2220 	}
2221 
2222 	ShrinkFifoMemory(f);
2223 
2224 	// KS
2225 	KS_INC(KS_READ_FIFO_COUNT);
2226 
2227 	return read_size;
2228 }
2229 
2230 // Rearrange the memory
ShrinkFifoMemory(FIFO * f)2231 void ShrinkFifoMemory(FIFO *f)
2232 {
2233 	// Validate arguments
2234 	if (f == NULL)
2235 	{
2236 		return;
2237 	}
2238 
2239 	if (f->fixed)
2240 	{
2241 		return;
2242 	}
2243 
2244 	// Rearrange the memory
2245 	if (f->pos >= FIFO_INIT_MEM_SIZE &&
2246 		f->memsize >= fifo_current_realloc_mem_size &&
2247 		(f->memsize / 2) > f->size)
2248 	{
2249 		void *new_p;
2250 		UINT new_size;
2251 
2252 		new_size = MAX(f->memsize / 2, FIFO_INIT_MEM_SIZE);
2253 		new_p = Malloc(new_size);
2254 		Copy(new_p, (UCHAR *)f->p + f->pos, f->size);
2255 
2256 		Free(f->p);
2257 
2258 		f->memsize = new_size;
2259 		f->p = new_p;
2260 		f->pos = 0;
2261 	}
2262 }
2263 
2264 // Write to the FIFO
WriteFifo(FIFO * f,void * p,UINT size)2265 void WriteFifo(FIFO *f, void *p, UINT size)
2266 {
2267 	UINT i, need_size;
2268 	bool realloc_flag;
2269 	// Validate arguments
2270 	if (f == NULL || size == 0)
2271 	{
2272 		return;
2273 	}
2274 
2275 	i = f->size;
2276 	f->size += size;
2277 	need_size = f->pos + f->size;
2278 	realloc_flag = false;
2279 
2280 	// Memory expansion
2281 	while (need_size > f->memsize)
2282 	{
2283 		f->memsize = MAX(f->memsize, FIFO_INIT_MEM_SIZE) * 3;
2284 		realloc_flag = true;
2285 	}
2286 
2287 	if (realloc_flag)
2288 	{
2289 		f->p = ReAlloc(f->p, f->memsize);
2290 	}
2291 
2292 	// Write the data
2293 	if (p != NULL)
2294 	{
2295 		Copy((UCHAR *)f->p + f->pos + i, p, size);
2296 	}
2297 
2298 	f->total_write_size += (UINT64)size;
2299 
2300 	// KS
2301 	KS_INC(KS_WRITE_FIFO_COUNT);
2302 }
2303 
2304 // Get the current pointer of the FIFO
GetFifoPointer(FIFO * f)2305 UCHAR *GetFifoPointer(FIFO *f)
2306 {
2307 	// Validate arguments
2308 	if (f == NULL)
2309 	{
2310 		return NULL;
2311 	}
2312 
2313 	return ((UCHAR *)f->p) + f->pos;
2314 }
FifoPtr(FIFO * f)2315 UCHAR *FifoPtr(FIFO *f)
2316 {
2317 	return GetFifoPointer(f);
2318 }
2319 
2320 // Get the size of the FIFO
FifoSize(FIFO * f)2321 UINT FifoSize(FIFO *f)
2322 {
2323 	// Validate arguments
2324 	if (f == NULL)
2325 	{
2326 		return 0;
2327 	}
2328 
2329 	return f->size;
2330 }
2331 
2332 // Release the FIFO
ReleaseFifo(FIFO * f)2333 void ReleaseFifo(FIFO *f)
2334 {
2335 	// Validate arguments
2336 	if (f == NULL)
2337 	{
2338 		return;
2339 	}
2340 
2341 	if (f->ref == NULL || Release(f->ref) == 0)
2342 	{
2343 		CleanupFifo(f);
2344 	}
2345 }
2346 
2347 // Clean-up the FIFO
CleanupFifo(FIFO * f)2348 void CleanupFifo(FIFO *f)
2349 {
2350 	// Validate arguments
2351 	if (f == NULL)
2352 	{
2353 		return;
2354 	}
2355 
2356 	DeleteLock(f->lock);
2357 	Free(f->p);
2358 	Free(f);
2359 
2360 	// KS
2361 	KS_INC(KS_FREEFIFO_COUNT);
2362 }
2363 
2364 // Initialize the FIFO system
InitFifo()2365 void InitFifo()
2366 {
2367 	fifo_current_realloc_mem_size = FIFO_REALLOC_MEM_SIZE;
2368 }
2369 
2370 // Create a FIFO
NewFifo()2371 FIFO *NewFifo()
2372 {
2373 	return NewFifoEx(false);
2374 }
NewFifoFast()2375 FIFO *NewFifoFast()
2376 {
2377 	return NewFifoEx(true);
2378 }
NewFifoEx(bool fast)2379 FIFO *NewFifoEx(bool fast)
2380 {
2381 	return NewFifoEx2(fast, false);
2382 }
NewFifoEx2(bool fast,bool fixed)2383 FIFO *NewFifoEx2(bool fast, bool fixed)
2384 {
2385 	FIFO *f;
2386 
2387 	// Memory allocation
2388 	f = ZeroMalloc(sizeof(FIFO));
2389 
2390 	if (fast == false)
2391 	{
2392 		f->lock = NewLock();
2393 		f->ref = NewRef();
2394 	}
2395 	else
2396 	{
2397 		f->lock = NULL;
2398 		f->ref = NULL;
2399 	}
2400 
2401 	f->size = f->pos = 0;
2402 	f->memsize = FIFO_INIT_MEM_SIZE;
2403 	f->p = Malloc(FIFO_INIT_MEM_SIZE);
2404 	f->fixed = false;
2405 
2406 	// KS
2407 	KS_INC(KS_NEWFIFO_COUNT);
2408 
2409 	return f;
2410 }
2411 
2412 // Set the default memory reclaiming size of the FIFO
SetFifoCurrentReallocMemSize(UINT size)2413 void SetFifoCurrentReallocMemSize(UINT size)
2414 {
2415 	if (size == 0)
2416 	{
2417 		size = FIFO_REALLOC_MEM_SIZE;
2418 	}
2419 
2420 	fifo_current_realloc_mem_size = size;
2421 }
2422 
2423 // Read a buffer from a file
FileToBuf(IO * o)2424 BUF *FileToBuf(IO *o)
2425 {
2426 	UCHAR hash1[MD5_SIZE], hash2[MD5_SIZE];
2427 	UINT size;
2428 	void *buf;
2429 	BUF *b;
2430 
2431 	// Validate arguments
2432 	if (o == NULL)
2433 	{
2434 		return NULL;
2435 	}
2436 
2437 	// Read the size
2438 	if (FileRead(o, &size, sizeof(size)) == false)
2439 	{
2440 		return NULL;
2441 	}
2442 	size = Endian32(size);
2443 
2444 	if (size > FileSize(o))
2445 	{
2446 		return NULL;
2447 	}
2448 
2449 	// Read a hash
2450 	if (FileRead(o, hash1, sizeof(hash1)) == false)
2451 	{
2452 		return NULL;
2453 	}
2454 
2455 	// Read from the buffer
2456 	buf = Malloc(size);
2457 	if (FileRead(o, buf, size) == false)
2458 	{
2459 		Free(buf);
2460 		return NULL;
2461 	}
2462 
2463 	// Take a hash
2464 	Md5(hash2, buf, size);
2465 
2466 	// Compare the hashes
2467 	if (Cmp(hash1, hash2, sizeof(hash1)) != 0)
2468 	{
2469 		// Hashes are different
2470 		Free(buf);
2471 		return NULL;
2472 	}
2473 
2474 	// Create a buffer
2475 	b = NewBuf();
2476 	WriteBuf(b, buf, size);
2477 	Free(buf);
2478 	b->Current = 0;
2479 
2480 	return b;
2481 }
2482 
2483 // Read a dump file into a buffer
ReadDump(char * filename)2484 BUF *ReadDump(char *filename)
2485 {
2486 	return ReadDumpWithMaxSize(filename, 0);
2487 }
ReadDumpWithMaxSize(char * filename,UINT max_size)2488 BUF *ReadDumpWithMaxSize(char *filename, UINT max_size)
2489 {
2490 	IO *o;
2491 	BUF *b;
2492 	UINT size;
2493 	void *data;
2494 	// Validate arguments
2495 	if (filename == NULL)
2496 	{
2497 		return NULL;
2498 	}
2499 
2500 	o = FileOpen(filename, false);
2501 	if (o == NULL)
2502 	{
2503 		return NULL;
2504 	}
2505 
2506 	size = FileSize(o);
2507 
2508 	if (max_size != 0)
2509 	{
2510 		if (size > max_size)
2511 		{
2512 			size = max_size;
2513 		}
2514 	}
2515 
2516 	data = Malloc(size);
2517 	FileRead(o, data, size);
2518 	FileClose(o);
2519 
2520 	b = NewBuf();
2521 	WriteBuf(b, data, size);
2522 	b->Current = 0;
2523 	Free(data);
2524 
2525 	return b;
2526 }
ReadDumpW(wchar_t * filename)2527 BUF *ReadDumpW(wchar_t *filename)
2528 {
2529 	return ReadDumpExW(filename, true);
2530 }
ReadDumpExW(wchar_t * filename,bool read_lock)2531 BUF *ReadDumpExW(wchar_t *filename, bool read_lock)
2532 {
2533 	IO *o;
2534 	BUF *b;
2535 	UINT size;
2536 	void *data;
2537 	// Validate arguments
2538 	if (filename == NULL)
2539 	{
2540 		return NULL;
2541 	}
2542 
2543 	o = FileOpenExW(filename, false, read_lock);
2544 	if (o == NULL)
2545 	{
2546 		return NULL;
2547 	}
2548 
2549 	size = FileSize(o);
2550 	data = Malloc(size);
2551 	FileRead(o, data, size);
2552 	FileClose(o);
2553 
2554 	b = NewBuf();
2555 	WriteBuf(b, data, size);
2556 	b->Current = 0;
2557 	Free(data);
2558 
2559 	return b;
2560 }
2561 
2562 // Write down the data
DumpDataW(void * data,UINT size,wchar_t * filename)2563 bool DumpDataW(void *data, UINT size, wchar_t *filename)
2564 {
2565 	IO *o;
2566 	// Validate arguments
2567 	if (filename == NULL || (size != 0 && data == NULL))
2568 	{
2569 		return false;
2570 	}
2571 
2572 	o = FileCreateW(filename);
2573 	if (o == NULL)
2574 	{
2575 		return false;
2576 	}
2577 	FileWrite(o, data, size);
2578 	FileClose(o);
2579 
2580 	return true;
2581 }
2582 
2583 // Dump the contents of the buffer to the file
DumpBuf(BUF * b,char * filename)2584 bool DumpBuf(BUF *b, char *filename)
2585 {
2586 	IO *o;
2587 	// Validate arguments
2588 	if (b == NULL || filename == NULL)
2589 	{
2590 		return false;
2591 	}
2592 
2593 	o = FileCreate(filename);
2594 	if (o == NULL)
2595 	{
2596 		return false;
2597 	}
2598 	FileWrite(o, b->Buf, b->Size);
2599 	FileClose(o);
2600 
2601 	return true;
2602 }
DumpBufW(BUF * b,wchar_t * filename)2603 bool DumpBufW(BUF *b, wchar_t *filename)
2604 {
2605 	IO *o;
2606 	// Validate arguments
2607 	if (b == NULL || filename == NULL)
2608 	{
2609 		return false;
2610 	}
2611 
2612 	o = FileCreateW(filename);
2613 	if (o == NULL)
2614 	{
2615 		return false;
2616 	}
2617 	FileWrite(o, b->Buf, b->Size);
2618 	FileClose(o);
2619 
2620 	return true;
2621 }
2622 
2623 // Write to the file only if the contents of the file is different
DumpBufWIfNecessary(BUF * b,wchar_t * filename)2624 bool DumpBufWIfNecessary(BUF *b, wchar_t *filename)
2625 {
2626 	BUF *now;
2627 	bool need = true;
2628 	// Validate arguments
2629 	if (b == NULL || filename == NULL)
2630 	{
2631 		return false;
2632 	}
2633 
2634 	now = ReadDumpW(filename);
2635 
2636 	if (now != NULL)
2637 	{
2638 		if (CompareBuf(now, b))
2639 		{
2640 			need = false;
2641 		}
2642 
2643 		FreeBuf(now);
2644 	}
2645 
2646 	if (need == false)
2647 	{
2648 		return true;
2649 	}
2650 	else
2651 	{
2652 		return DumpBufW(b, filename);
2653 	}
2654 }
2655 
2656 // Write the buffer to a file
BufToFile(IO * o,BUF * b)2657 bool BufToFile(IO *o, BUF *b)
2658 {
2659 	UCHAR hash[MD5_SIZE];
2660 	UINT size;
2661 
2662 	// Validate arguments
2663 	if (o == NULL || b == NULL)
2664 	{
2665 		return false;
2666 	}
2667 
2668 	// Hash the data
2669 	Md5(hash, b->Buf, b->Size);
2670 
2671 	size = Endian32(b->Size);
2672 
2673 	// Write the size
2674 	if (FileWrite(o, &size, sizeof(size)) == false)
2675 	{
2676 		return false;
2677 	}
2678 
2679 	// Write a hash
2680 	if (FileWrite(o, hash, sizeof(hash)) == false)
2681 	{
2682 		return false;
2683 	}
2684 
2685 	// Write the data
2686 	if (FileWrite(o, b->Buf, b->Size) == false)
2687 	{
2688 		return false;
2689 	}
2690 
2691 	return true;
2692 }
2693 
2694 // Create a buffer from memory
NewBufFromMemory(void * buf,UINT size)2695 BUF *NewBufFromMemory(void *buf, UINT size)
2696 {
2697 	BUF *b;
2698 	// Validate arguments
2699 	if (buf == NULL && size != 0)
2700 	{
2701 		return NULL;
2702 	}
2703 
2704 	b = NewBuf();
2705 	WriteBuf(b, buf, size);
2706 	SeekBufToBegin(b);
2707 
2708 	return b;
2709 }
2710 
2711 // Creating a buffer
NewBuf()2712 BUF *NewBuf()
2713 {
2714 	BUF *b;
2715 
2716 	// Memory allocation
2717 	b = Malloc(sizeof(BUF));
2718 	b->Buf = Malloc(INIT_BUF_SIZE);
2719 	b->Size = 0;
2720 	b->Current = 0;
2721 	b->SizeReserved = INIT_BUF_SIZE;
2722 
2723 	// KS
2724 	KS_INC(KS_NEWBUF_COUNT);
2725 	KS_INC(KS_CURRENT_BUF_COUNT);
2726 
2727 	return b;
2728 }
2729 
2730 // Clearing the buffer
ClearBuf(BUF * b)2731 void ClearBuf(BUF *b)
2732 {
2733 	// Validate arguments
2734 	if (b == NULL)
2735 	{
2736 		return;
2737 	}
2738 
2739 	b->Size = 0;
2740 	b->Current = 0;
2741 }
2742 
2743 // Write to the buffer
WriteBuf(BUF * b,void * buf,UINT size)2744 void WriteBuf(BUF *b, void *buf, UINT size)
2745 {
2746 	UINT new_size;
2747 	// Validate arguments
2748 	if (b == NULL || buf == NULL || size == 0)
2749 	{
2750 		return;
2751 	}
2752 
2753 	new_size = b->Current + size;
2754 	if (new_size > b->Size)
2755 	{
2756 		// Adjust the size
2757 		AdjustBufSize(b, new_size);
2758 	}
2759 	if (b->Buf != NULL)
2760 	{
2761 		Copy((UCHAR *)b->Buf + b->Current, buf, size);
2762 	}
2763 	b->Current += size;
2764 	b->Size = new_size;
2765 
2766 	// KS
2767 	KS_INC(KS_WRITE_BUF_COUNT);
2768 }
2769 
2770 // Append a string to the buffer
AddBufStr(BUF * b,char * str)2771 void AddBufStr(BUF *b, char *str)
2772 {
2773 	// Validate arguments
2774 	if (b == NULL || str == NULL)
2775 	{
2776 		return;
2777 	}
2778 
2779 	WriteBuf(b, str, StrLen(str));
2780 }
2781 
2782 // Write a line to the buffer
WriteBufLine(BUF * b,char * str)2783 void WriteBufLine(BUF *b, char *str)
2784 {
2785 	char *crlf = "\r\n";
2786 	// Validate arguments
2787 	if (b == NULL || str == NULL)
2788 	{
2789 		return;
2790 	}
2791 
2792 	WriteBuf(b, str, StrLen(str));
2793 	WriteBuf(b, crlf, StrLen(crlf));
2794 }
2795 
2796 // Write a string to a buffer
WriteBufStr(BUF * b,char * str)2797 bool WriteBufStr(BUF *b, char *str)
2798 {
2799 	UINT len;
2800 	// Validate arguments
2801 	if (b == NULL || str == NULL)
2802 	{
2803 		return false;
2804 	}
2805 
2806 	// String length
2807 	len = StrLen(str);
2808 	if (WriteBufInt(b, len + 1) == false)
2809 	{
2810 		return false;
2811 	}
2812 
2813 	// String body
2814 	WriteBuf(b, str, len);
2815 
2816 	return true;
2817 }
2818 
2819 // Read a string from the buffer
ReadBufStr(BUF * b,char * str,UINT size)2820 bool ReadBufStr(BUF *b, char *str, UINT size)
2821 {
2822 	UINT len;
2823 	UINT read_size;
2824 	// Validate arguments
2825 	if (b == NULL || str == NULL || size == 0)
2826 	{
2827 		return false;
2828 	}
2829 
2830 	// Read the length of the string
2831 	len = ReadBufInt(b);
2832 	if (len == 0)
2833 	{
2834 		return false;
2835 	}
2836 	len--;
2837 	if (len <= (size - 1))
2838 	{
2839 		size = len + 1;
2840 	}
2841 
2842 	read_size = MIN(len, (size - 1));
2843 
2844 	// Read the string body
2845 	if (ReadBuf(b, str, read_size) != read_size)
2846 	{
2847 		return false;
2848 	}
2849 	if (read_size < len)
2850 	{
2851 		ReadBuf(b, NULL, len - read_size);
2852 	}
2853 	str[read_size] = 0;
2854 
2855 	return true;
2856 }
2857 
2858 // Write a 64 bit integer to the buffer
WriteBufInt64(BUF * b,UINT64 value)2859 bool WriteBufInt64(BUF *b, UINT64 value)
2860 {
2861 	// Validate arguments
2862 	if (b == NULL)
2863 	{
2864 		return false;
2865 	}
2866 
2867 	value = Endian64(value);
2868 
2869 	WriteBuf(b, &value, sizeof(UINT64));
2870 	return true;
2871 }
2872 
2873 // Write an integer in the the buffer
WriteBufInt(BUF * b,UINT value)2874 bool WriteBufInt(BUF *b, UINT value)
2875 {
2876 	// Validate arguments
2877 	if (b == NULL)
2878 	{
2879 		return false;
2880 	}
2881 
2882 	value = Endian32(value);
2883 
2884 	WriteBuf(b, &value, sizeof(UINT));
2885 	return true;
2886 }
2887 
2888 // Write a short integer in the the buffer
WriteBufShort(BUF * b,USHORT value)2889 bool WriteBufShort(BUF *b, USHORT value)
2890 {
2891 	// Validate arguments
2892 	if (b == NULL)
2893 	{
2894 		return false;
2895 	}
2896 
2897 	value = Endian16(value);
2898 
2899 	WriteBuf(b, &value, sizeof(USHORT));
2900 	return true;
2901 }
2902 
2903 // Write a UCHAR to the buffer
WriteBufChar(BUF * b,UCHAR uc)2904 bool WriteBufChar(BUF *b, UCHAR uc)
2905 {
2906 	// Validate arguments
2907 	if (b == NULL)
2908 	{
2909 		return false;
2910 	}
2911 
2912 	WriteBuf(b, &uc, 1);
2913 
2914 	return true;
2915 }
2916 
2917 // Read a UCHAR from the buffer
ReadBufChar(BUF * b)2918 UCHAR ReadBufChar(BUF *b)
2919 {
2920 	UCHAR uc;
2921 	// Validate arguments
2922 	if (b == NULL)
2923 	{
2924 		return 0;
2925 	}
2926 
2927 	if (ReadBuf(b, &uc, 1) != 1)
2928 	{
2929 		return 0;
2930 	}
2931 
2932 	return uc;
2933 }
2934 
2935 // Read a 64bit integer from the buffer
ReadBufInt64(BUF * b)2936 UINT64 ReadBufInt64(BUF *b)
2937 {
2938 	UINT64 value;
2939 	// Validate arguments
2940 	if (b == NULL)
2941 	{
2942 		return 0;
2943 	}
2944 
2945 	if (ReadBuf(b, &value, sizeof(UINT64)) != sizeof(UINT64))
2946 	{
2947 		return 0;
2948 	}
2949 	return Endian64(value);
2950 }
2951 
2952 // Read an integer from the buffer
ReadBufInt(BUF * b)2953 UINT ReadBufInt(BUF *b)
2954 {
2955 	UINT value;
2956 	// Validate arguments
2957 	if (b == NULL)
2958 	{
2959 		return 0;
2960 	}
2961 
2962 	if (ReadBuf(b, &value, sizeof(UINT)) != sizeof(UINT))
2963 	{
2964 		return 0;
2965 	}
2966 	return Endian32(value);
2967 }
2968 
2969 // Read a short integer from the buffer
ReadBufShort(BUF * b)2970 USHORT ReadBufShort(BUF *b)
2971 {
2972 	USHORT value;
2973 	// Validate arguments
2974 	if (b == NULL)
2975 	{
2976 		return 0;
2977 	}
2978 
2979 	if (ReadBuf(b, &value, sizeof(USHORT)) != sizeof(USHORT))
2980 	{
2981 		return 0;
2982 	}
2983 	return Endian16(value);
2984 }
2985 
2986 // Write the buffer to a buffer
WriteBufBuf(BUF * b,BUF * bb)2987 void WriteBufBuf(BUF *b, BUF *bb)
2988 {
2989 	// Validate arguments
2990 	if (b == NULL || bb == NULL)
2991 	{
2992 		return;
2993 	}
2994 
2995 	WriteBuf(b, bb->Buf, bb->Size);
2996 }
2997 
2998 // Write the buffer (from the offset) to a buffer
WriteBufBufWithOffset(BUF * b,BUF * bb)2999 void WriteBufBufWithOffset(BUF *b, BUF *bb)
3000 {
3001 	// Validate arguments
3002 	if (b == NULL || bb == NULL)
3003 	{
3004 		return;
3005 	}
3006 
3007 	WriteBuf(b, ((UCHAR *)bb->Buf) + bb->Current, bb->Size - bb->Current);
3008 }
3009 
3010 // Skip UTF-8 BOM
BufSkipUtf8Bom(BUF * b)3011 bool BufSkipUtf8Bom(BUF *b)
3012 {
3013 	if (b == NULL)
3014 	{
3015 		return false;
3016 	}
3017 
3018 	SeekBufToBegin(b);
3019 
3020 	if (b->Size >= 3)
3021 	{
3022 		UCHAR *data = b->Buf;
3023 
3024 		if (data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF)
3025 		{
3026 			SeekBuf(b, 3, 1);
3027 
3028 			return true;
3029 		}
3030 	}
3031 
3032 	return false;
3033 }
3034 
3035 // Read into a buffer from the buffer
ReadBufFromBuf(BUF * b,UINT size)3036 BUF *ReadBufFromBuf(BUF *b, UINT size)
3037 {
3038 	BUF *ret;
3039 	UCHAR *data;
3040 	// Validate arguments
3041 	if (b == NULL)
3042 	{
3043 		return NULL;
3044 	}
3045 
3046 	data = Malloc(size);
3047 	if (ReadBuf(b, data, size) != size)
3048 	{
3049 		Free(data);
3050 		return NULL;
3051 	}
3052 
3053 	ret = NewBuf();
3054 	WriteBuf(ret, data, size);
3055 	SeekBuf(ret, 0, 0);
3056 
3057 	Free(data);
3058 
3059 	return ret;
3060 }
3061 
3062 // Read from the buffer
ReadBuf(BUF * b,void * buf,UINT size)3063 UINT ReadBuf(BUF *b, void *buf, UINT size)
3064 {
3065 	UINT size_read;
3066 	// Validate arguments
3067 	if (b == NULL || size == 0)
3068 	{
3069 		return 0;
3070 	}
3071 
3072 	if (b->Buf == NULL)
3073 	{
3074 		Zero(buf, size);
3075 		return 0;
3076 	}
3077 	size_read = size;
3078 	if ((b->Current + size) >= b->Size)
3079 	{
3080 		size_read = b->Size - b->Current;
3081 		if (buf != NULL)
3082 		{
3083 			Zero((UCHAR *)buf + size_read, size - size_read);
3084 		}
3085 	}
3086 
3087 	if (buf != NULL)
3088 	{
3089 		Copy(buf, (UCHAR *)b->Buf + b->Current, size_read);
3090 	}
3091 
3092 	b->Current += size_read;
3093 
3094 	// KS
3095 	KS_INC(KS_READ_BUF_COUNT);
3096 
3097 	return size_read;
3098 }
3099 
3100 // Adjusting the buffer size
AdjustBufSize(BUF * b,UINT new_size)3101 void AdjustBufSize(BUF *b, UINT new_size)
3102 {
3103 	// Validate arguments
3104 	if (b == NULL)
3105 	{
3106 		return;
3107 	}
3108 
3109 	if (b->SizeReserved >= new_size)
3110 	{
3111 		return;
3112 	}
3113 
3114 	while (b->SizeReserved < new_size)
3115 	{
3116 		b->SizeReserved = b->SizeReserved * 2;
3117 	}
3118 	b->Buf = ReAlloc(b->Buf, b->SizeReserved);
3119 
3120 	// KS
3121 	KS_INC(KS_ADJUST_BUFSIZE_COUNT);
3122 }
3123 
3124 // Seek to the beginning of the buffer
SeekBufToBegin(BUF * b)3125 void SeekBufToBegin(BUF *b)
3126 {
3127 	// Validate arguments
3128 	if (b == NULL)
3129 	{
3130 		return;
3131 	}
3132 
3133 	SeekBuf(b, 0, 0);
3134 }
3135 
3136 // Seek to end of the buffer
SeekBufToEnd(BUF * b)3137 void SeekBufToEnd(BUF *b)
3138 {
3139 	// Validate arguments
3140 	if (b == NULL)
3141 	{
3142 		return;
3143 	}
3144 
3145 	SeekBuf(b, b->Size, 0);
3146 }
3147 
3148 // Seek of the buffer
SeekBuf(BUF * b,UINT offset,int mode)3149 void SeekBuf(BUF *b, UINT offset, int mode)
3150 {
3151 	UINT new_pos;
3152 	// Validate arguments
3153 	if (b == NULL)
3154 	{
3155 		return;
3156 	}
3157 
3158 	if (mode == 0)
3159 	{
3160 		// Absolute position
3161 		new_pos = offset;
3162 	}
3163 	else
3164 	{
3165 		if (mode > 0)
3166 		{
3167 			// Move Right
3168 			new_pos = b->Current + offset;
3169 		}
3170 		else
3171 		{
3172 			// Move Left
3173 			if (b->Current >= offset)
3174 			{
3175 				new_pos = b->Current - offset;
3176 			}
3177 			else
3178 			{
3179 				new_pos = 0;
3180 			}
3181 		}
3182 	}
3183 	b->Current = MAKESURE(new_pos, 0, b->Size);
3184 
3185 	KS_INC(KS_SEEK_BUF_COUNT);
3186 }
3187 
3188 // Free the buffer
FreeBuf(BUF * b)3189 void FreeBuf(BUF *b)
3190 {
3191 	// Validate arguments
3192 	if (b == NULL)
3193 	{
3194 		return;
3195 	}
3196 
3197 	// Memory release
3198 	Free(b->Buf);
3199 	Free(b);
3200 
3201 	// KS
3202 	KS_INC(KS_FREEBUF_COUNT);
3203 	KS_DEC(KS_CURRENT_BUF_COUNT);
3204 }
3205 
3206 // Compare BUFs whether two are identical
CompareBuf(BUF * b1,BUF * b2)3207 bool CompareBuf(BUF *b1, BUF *b2)
3208 {
3209 	// Validate arguments
3210 	if (b1 == NULL && b2 == NULL)
3211 	{
3212 		return true;
3213 	}
3214 	if (b1 == NULL || b2 == NULL)
3215 	{
3216 		return false;
3217 	}
3218 
3219 	if (b1->Size != b2->Size)
3220 	{
3221 		return false;
3222 	}
3223 
3224 	if (Cmp(b1->Buf, b2->Buf, b1->Size) != 0)
3225 	{
3226 		return false;
3227 	}
3228 
3229 	return true;
3230 }
3231 
3232 // Create a buffer from the memory area
MemToBuf(void * data,UINT size)3233 BUF *MemToBuf(void *data, UINT size)
3234 {
3235 	BUF *b;
3236 	// Validate arguments
3237 	if (data == NULL && size != 0)
3238 	{
3239 		return NULL;
3240 	}
3241 
3242 	b = NewBuf();
3243 	WriteBuf(b, data, size);
3244 	SeekBuf(b, 0, 0);
3245 
3246 	return b;
3247 }
3248 
3249 // Creating a random number buffer
RandBuf(UINT size)3250 BUF *RandBuf(UINT size)
3251 {
3252 	void *data = Malloc(size);
3253 	BUF *ret;
3254 
3255 	Rand(data, size);
3256 
3257 	ret = MemToBuf(data, size);
3258 
3259 	Free(data);
3260 
3261 	return ret;
3262 }
3263 
3264 // Read the rest part of the buffer
ReadRemainBuf(BUF * b)3265 BUF *ReadRemainBuf(BUF *b)
3266 {
3267 	UINT size;
3268 	// Validate arguments
3269 	if (b == NULL)
3270 	{
3271 		return NULL;
3272 	}
3273 
3274 	if (b->Size < b->Current)
3275 	{
3276 		return NULL;
3277 	}
3278 
3279 	size = b->Size - b->Current;
3280 
3281 	return ReadBufFromBuf(b, size);
3282 }
3283 
3284 // Get the length of the rest
ReadBufRemainSize(BUF * b)3285 UINT ReadBufRemainSize(BUF *b)
3286 {
3287 	// Validate arguments
3288 	if (b == NULL)
3289 	{
3290 		return 0;
3291 	}
3292 
3293 	if (b->Size < b->Current)
3294 	{
3295 		return 0;
3296 	}
3297 
3298 	return b->Size - b->Current;
3299 }
3300 
3301 // Clone the buffer
CloneBuf(BUF * b)3302 BUF *CloneBuf(BUF *b)
3303 {
3304 	BUF *bb;
3305 	// Validate arguments
3306 	if (b == NULL)
3307 	{
3308 		return NULL;
3309 	}
3310 
3311 	bb = MemToBuf(b->Buf, b->Size);
3312 
3313 	return bb;
3314 }
3315 
3316 // Endian conversion of Unicode string
EndianUnicode(wchar_t * str)3317 void EndianUnicode(wchar_t *str)
3318 {
3319 	UINT i, len;
3320 	// Validate arguments
3321 	if (str == NULL)
3322 	{
3323 		return;
3324 	}
3325 	len = UniStrLen(str);
3326 
3327 	for (i = 0;i < len;i++)
3328 	{
3329 		str[i] = Endian16(str[i]);
3330 	}
3331 }
3332 
3333 // Endian conversion 16bit
Endian16(USHORT src)3334 USHORT Endian16(USHORT src)
3335 {
3336 	int x = 1;
3337 	if (*((char *)&x))
3338 	{
3339 		return Swap16(src);
3340 	}
3341 	else
3342 	{
3343 		return src;
3344 	}
3345 }
3346 
3347 // Endian conversion 32bit
Endian32(UINT src)3348 UINT Endian32(UINT src)
3349 {
3350 	int x = 1;
3351 	if (*((char *)&x))
3352 	{
3353 		return Swap32(src);
3354 	}
3355 	else
3356 	{
3357 		return src;
3358 	}
3359 }
3360 
3361 // Endian conversion 64bit
Endian64(UINT64 src)3362 UINT64 Endian64(UINT64 src)
3363 {
3364 	int x = 1;
3365 	if (*((char *)&x))
3366 	{
3367 		return Swap64(src);
3368 	}
3369 	else
3370 	{
3371 		return src;
3372 	}
3373 }
3374 
3375 // 16bit swap
Swap16(USHORT value)3376 USHORT Swap16(USHORT value)
3377 {
3378 	USHORT r;
3379 	((BYTE *)&r)[0] = ((BYTE *)&value)[1];
3380 	((BYTE *)&r)[1] = ((BYTE *)&value)[0];
3381 	return r;
3382 }
3383 
3384 // 32bit swap
Swap32(UINT value)3385 UINT Swap32(UINT value)
3386 {
3387 	UINT r;
3388 	((BYTE *)&r)[0] = ((BYTE *)&value)[3];
3389 	((BYTE *)&r)[1] = ((BYTE *)&value)[2];
3390 	((BYTE *)&r)[2] = ((BYTE *)&value)[1];
3391 	((BYTE *)&r)[3] = ((BYTE *)&value)[0];
3392 	return r;
3393 }
3394 
3395 // 64-bit swap
Swap64(UINT64 value)3396 UINT64 Swap64(UINT64 value)
3397 {
3398 	UINT64 r;
3399 	((BYTE *)&r)[0] = ((BYTE *)&value)[7];
3400 	((BYTE *)&r)[1] = ((BYTE *)&value)[6];
3401 	((BYTE *)&r)[2] = ((BYTE *)&value)[5];
3402 	((BYTE *)&r)[3] = ((BYTE *)&value)[4];
3403 	((BYTE *)&r)[4] = ((BYTE *)&value)[3];
3404 	((BYTE *)&r)[5] = ((BYTE *)&value)[2];
3405 	((BYTE *)&r)[6] = ((BYTE *)&value)[1];
3406 	((BYTE *)&r)[7] = ((BYTE *)&value)[0];
3407 	return r;
3408 }
3409 
3410 // Base64 encode
Encode64(char * dst,char * src)3411 UINT Encode64(char *dst, char *src)
3412 {
3413 	// Validate arguments
3414 	if (dst == NULL || src == NULL)
3415 	{
3416 		return 0;
3417 	}
3418 
3419 	return B64_Encode(dst, src, StrLen(src));
3420 }
3421 
3422 // Base64 decoding
Decode64(char * dst,char * src)3423 UINT Decode64(char *dst, char *src)
3424 {
3425 	// Validate arguments
3426 	if (dst == NULL || src == NULL)
3427 	{
3428 		return 0;
3429 	}
3430 
3431 	return B64_Decode(dst, src, StrLen(src));
3432 }
3433 
3434 // Base64 encode
B64_Encode(char * set,char * source,int len)3435 int B64_Encode(char *set, char *source, int len)
3436 {
3437 	BYTE *src;
3438 	int i,j;
3439 	src = (BYTE *)source;
3440 	j = 0;
3441 	i = 0;
3442 	if (!len)
3443 	{
3444 		return 0;
3445 	}
3446 	while (true)
3447 	{
3448 		if (i >= len)
3449 		{
3450 			return j;
3451 		}
3452 		if (set)
3453 		{
3454 			set[j] = B64_CodeToChar((src[i]) >> 2);
3455 		}
3456 		if (i + 1 >= len)
3457 		{
3458 			if (set)
3459 			{
3460 				set[j + 1] = B64_CodeToChar((src[i] & 0x03) << 4);
3461 				set[j + 2] = '=';
3462 				set[j + 3] = '=';
3463 			}
3464 			return j + 4;
3465 		}
3466 		if (set)
3467 		{
3468 			set[j + 1] = B64_CodeToChar(((src[i] & 0x03) << 4) + ((src[i + 1] >> 4)));
3469 		}
3470 		if (i + 2 >= len)
3471 		{
3472 			if (set)
3473 			{
3474 				set[j + 2] = B64_CodeToChar((src[i + 1] & 0x0f) << 2);
3475 				set[j + 3] = '=';
3476 			}
3477 			return j + 4;
3478 		}
3479 		if (set)
3480 		{
3481 			set[j + 2] = B64_CodeToChar(((src[i + 1] & 0x0f) << 2) + ((src[i + 2] >> 6)));
3482 			set[j + 3] = B64_CodeToChar(src[i + 2] & 0x3f);
3483 		}
3484 		i += 3;
3485 		j += 4;
3486 	}
3487 }
3488 
3489 // Base64 decode
B64_Decode(char * set,char * source,int len)3490 int B64_Decode(char *set, char *source, int len)
3491 {
3492 	int i,j;
3493 	char a1,a2,a3,a4;
3494 	char *src;
3495 	int f1,f2,f3,f4;
3496 	src = source;
3497 	i = 0;
3498 	j = 0;
3499 	while (true)
3500 	{
3501 		f1 = f2 = f3 = f4 = 0;
3502 		if (i >= len)
3503 		{
3504 			break;
3505 		}
3506 		f1 = 1;
3507 		a1 = B64_CharToCode(src[i]);
3508 		if (a1 == -1)
3509 		{
3510 			f1 = 0;
3511 		}
3512 		if (i >= len + 1)
3513 		{
3514 			a2 = 0;
3515 		}
3516 		else
3517 		{
3518 			a2 = B64_CharToCode(src[i + 1]);
3519 			f2 = 1;
3520 			if (a2 == -1)
3521 			{
3522 				f2 = 0;
3523 			}
3524 		}
3525 		if (i >= len + 2)
3526 		{
3527 			a3 = 0;
3528 		}
3529 		else
3530 		{
3531 			a3 = B64_CharToCode(src[i + 2]);
3532 			f3 = 1;
3533 			if (a3 == -1)
3534 			{
3535 				f3 = 0;
3536 			}
3537 		}
3538 		if (i >= len + 3)
3539 		{
3540 			a4 = 0;
3541 		}
3542 		else
3543 		{
3544 			a4 = B64_CharToCode(src[i + 3]);
3545 			f4 = 1;
3546 			if (a4 == -1)
3547 			{
3548 				f4 = 0;
3549 			}
3550 		}
3551 		if (f1 && f2)
3552 		{
3553 			if (set)
3554 			{
3555 				set[j] = (a1 << 2) + (a2 >> 4);
3556 			}
3557 			j++;
3558 		}
3559 		if (f2 && f3)
3560 		{
3561 			if (set)
3562 			{
3563 				set[j] = (a2 << 4) + (a3 >> 2);
3564 			}
3565 			j++;
3566 		}
3567 		if (f3 && f4)
3568 		{
3569 			if (set)
3570 			{
3571 				set[j] = (a3 << 6) + a4;
3572 			}
3573 			j++;
3574 		}
3575 		i += 4;
3576 	}
3577 	return j;
3578 }
3579 
3580 // Base64 : Convert a code to a character
B64_CodeToChar(BYTE c)3581 char B64_CodeToChar(BYTE c)
3582 {
3583 	BYTE r;
3584 	r = '=';
3585 	if (c <= 0x19)
3586 	{
3587 		r = c + 'A';
3588 	}
3589 	if (c >= 0x1a && c <= 0x33)
3590 	{
3591 		r = c - 0x1a + 'a';
3592 	}
3593 	if (c >= 0x34 && c <= 0x3d)
3594 	{
3595 		r = c - 0x34 + '0';
3596 	}
3597 	if (c == 0x3e)
3598 	{
3599 		r = '+';
3600 	}
3601 	if (c == 0x3f)
3602 	{
3603 		r = '/';
3604 	}
3605 	return r;
3606 }
3607 
3608 // Base64 : Convert a character to a code
B64_CharToCode(char c)3609 char B64_CharToCode(char c)
3610 {
3611 	if (c >= 'A' && c <= 'Z')
3612 	{
3613 		return c - 'A';
3614 	}
3615 	if (c >= 'a' && c <= 'z')
3616 	{
3617 		return c - 'a' + 0x1a;
3618 	}
3619 	if (c >= '0' && c <= '9')
3620 	{
3621 		return c - '0' + 0x34;
3622 	}
3623 	if (c == '+')
3624 	{
3625 		return 0x3e;
3626 	}
3627 	if (c == '/')
3628 	{
3629 		return 0x3f;
3630 	}
3631 	if (c == '=')
3632 	{
3633 		return -1;
3634 	}
3635 	return 0;
3636 }
3637 
3638 // Malloc
Malloc(UINT size)3639 void *Malloc(UINT size)
3640 {
3641 	return MallocEx(size, false);
3642 }
MallocEx(UINT size,bool zero_clear_when_free)3643 void *MallocEx(UINT size, bool zero_clear_when_free)
3644 {
3645 	MEMTAG *tag;
3646 	UINT real_size;
3647 
3648 	real_size = CALC_MALLOCSIZE(size);
3649 
3650 	tag = InternalMalloc(real_size);
3651 
3652 	Zero(tag, sizeof(MEMTAG));
3653 	tag->Magic = MEMTAG_MAGIC;
3654 	tag->Size = size;
3655 	tag->ZeroFree = zero_clear_when_free;
3656 
3657 	return MEMTAG_TO_POINTER(tag);
3658 }
3659 
3660 // Get memory size
GetMemSize(void * addr)3661 UINT GetMemSize(void *addr)
3662 {
3663 	MEMTAG *tag;
3664 	// Validate arguments
3665 	if (IS_NULL_POINTER(addr))
3666 	{
3667 		return 0;
3668 	}
3669 
3670 	tag = POINTER_TO_MEMTAG(addr);
3671 	CheckMemTag(tag);
3672 
3673 	return tag->Size;
3674 }
3675 
3676 // ReAlloc
ReAlloc(void * addr,UINT size)3677 void *ReAlloc(void *addr, UINT size)
3678 {
3679 	MEMTAG *tag;
3680 	bool zerofree;
3681 	// Validate arguments
3682 	if (IS_NULL_POINTER(addr))
3683 	{
3684 		return NULL;
3685 	}
3686 
3687 	tag = POINTER_TO_MEMTAG(addr);
3688 	CheckMemTag(tag);
3689 
3690 	zerofree = tag->ZeroFree;
3691 
3692 	if (tag->Size == size)
3693 	{
3694 		// No size change
3695 		return addr;
3696 	}
3697 	else
3698 	{
3699 		if (zerofree)
3700 		{
3701 			// Size changed (zero clearing required)
3702 			void *new_p = MallocEx(size, true);
3703 
3704 			if (tag->Size <= size)
3705 			{
3706 				// Size expansion
3707 				Copy(new_p, addr, tag->Size);
3708 			}
3709 			else
3710 			{
3711 				// Size reduction
3712 				Copy(new_p, addr, size);
3713 			}
3714 
3715 			// Release the old block
3716 			Free(addr);
3717 
3718 			return new_p;
3719 		}
3720 		else
3721 		{
3722 			// Size changed
3723 			MEMTAG *tag2 = InternalReAlloc(tag, CALC_MALLOCSIZE(size));
3724 
3725 			Zero(tag2, sizeof(MEMTAG));
3726 			tag2->Magic = MEMTAG_MAGIC;
3727 			tag2->Size = size;
3728 
3729 			return MEMTAG_TO_POINTER(tag2);
3730 		}
3731 	}
3732 }
3733 
3734 // Free
Free(void * addr)3735 void Free(void *addr)
3736 {
3737 	MEMTAG *tag;
3738 	// Validate arguments
3739 	if (IS_NULL_POINTER(addr))
3740 	{
3741 		return;
3742 	}
3743 
3744 	tag = POINTER_TO_MEMTAG(addr);
3745 	CheckMemTag(tag);
3746 
3747 	if (tag->ZeroFree)
3748 	{
3749 		// Zero clear
3750 		Zero(addr, tag->Size);
3751 	}
3752 
3753 	// Memory release
3754 	tag->Magic = 0;
3755 	InternalFree(tag);
3756 }
3757 
3758 // Free and set pointer's value to NULL
FreeSafe(void ** addr)3759 void FreeSafe(void **addr)
3760 {
3761 	Free(*addr);
3762 	*addr = NULL;
3763 }
3764 
3765 // Check the memtag
CheckMemTag(MEMTAG * tag)3766 void CheckMemTag(MEMTAG *tag)
3767 {
3768 	if (IsTrackingEnabled() == false)
3769 	{
3770 		return;
3771 	}
3772 
3773 	// Validate arguments
3774 	if (tag == NULL)
3775 	{
3776 		AbortExitEx("CheckMemTag: tag == NULL");
3777 		return;
3778 	}
3779 
3780 	if (tag->Magic != MEMTAG_MAGIC)
3781 	{
3782 		AbortExitEx("CheckMemTag: tag->Magic != MEMTAG_MAGIC");
3783 		return;
3784 	}
3785 }
3786 
3787 // ZeroMalloc
ZeroMalloc(UINT size)3788 void *ZeroMalloc(UINT size)
3789 {
3790 	return ZeroMallocEx(size, false);
3791 }
ZeroMallocEx(UINT size,bool zero_clear_when_free)3792 void *ZeroMallocEx(UINT size, bool zero_clear_when_free)
3793 {
3794 	void *p = MallocEx(size, zero_clear_when_free);
3795 	Zero(p, size);
3796 	return p;
3797 }
3798 
3799 // Memory allocation
InternalMalloc(UINT size)3800 void *InternalMalloc(UINT size)
3801 {
3802 	void *addr;
3803 	UINT retry = 0;
3804 	size = MORE(size, 1);
3805 
3806 	// KS
3807 	KS_INC(KS_MALLOC_COUNT);
3808 	KS_INC(KS_TOTAL_MEM_COUNT);
3809 	KS_ADD(KS_TOTAL_MEM_SIZE, size);
3810 	KS_INC(KS_CURRENT_MEM_COUNT);
3811 
3812 	// Attempt to allocate memory until success
3813 	while (true)
3814 	{
3815 		if ((retry++) > MEMORY_MAX_RETRY)
3816 		{
3817 			AbortExitEx("InternalMalloc: error: malloc() failed.\n\n");
3818 		}
3819 		addr = OSMemoryAlloc(size);
3820 		if (addr != NULL)
3821 		{
3822 			break;
3823 		}
3824 
3825 		OSSleep(MEMORY_SLEEP_TIME);
3826 	}
3827 
3828 	TrackNewObj(POINTER_TO_UINT64(addr), "MEM", size);
3829 
3830 	return addr;
3831 }
3832 
3833 // Memory release
InternalFree(void * addr)3834 void InternalFree(void *addr)
3835 {
3836 	// Validate arguments
3837 	if (addr == NULL)
3838 	{
3839 		return;
3840 	}
3841 
3842 	// KS
3843 	KS_DEC(KS_CURRENT_MEM_COUNT);
3844 	KS_INC(KS_FREE_COUNT);
3845 
3846 	TrackDeleteObj(POINTER_TO_UINT64(addr));
3847 
3848 	// Memory release
3849 	OSMemoryFree(addr);
3850 }
3851 
3852 // Memory reallocation
InternalReAlloc(void * addr,UINT size)3853 void *InternalReAlloc(void *addr, UINT size)
3854 {
3855 	void *new_addr;
3856 	UINT retry = 0;
3857 	size = MORE(size, 1);
3858 
3859 	// KS
3860 	KS_INC(KS_REALLOC_COUNT);
3861 	KS_ADD(KS_TOTAL_MEM_SIZE, size);
3862 
3863 	// Attempt to allocate memory until success
3864 	while (true)
3865 	{
3866 		if ((retry++) > MEMORY_MAX_RETRY)
3867 		{
3868 			AbortExitEx("InternalReAlloc: error: realloc() failed.\n\n");
3869 		}
3870 		new_addr = OSMemoryReAlloc(addr, size);
3871 		if (new_addr != NULL)
3872 		{
3873 			break;
3874 		}
3875 
3876 		OSSleep(MEMORY_SLEEP_TIME);
3877 	}
3878 
3879 	TrackChangeObjSize(POINTER_TO_UINT64(addr), size, POINTER_TO_UINT64(new_addr));
3880 
3881 	return new_addr;
3882 }
3883 
3884 // Add the heading space to the memory area
AddHead(void * src,UINT src_size,void * head,UINT head_size)3885 void *AddHead(void *src, UINT src_size, void *head, UINT head_size)
3886 {
3887 	void *ret;
3888 	UINT ret_size;
3889 	// Validate arguments
3890 	if ((src == NULL && src_size != 0) || (head == NULL && head_size != 0))
3891 	{
3892 		return NULL;
3893 	}
3894 
3895 	ret_size = src_size + head_size;
3896 
3897 	ret = Malloc(ret_size);
3898 
3899 	Copy(ret, head, head_size);
3900 
3901 	Copy(((UCHAR *)ret) + head_size, src, src_size);
3902 
3903 	return ret;
3904 }
3905 
3906 // Clone the memory area
Clone(void * addr,UINT size)3907 void *Clone(void *addr, UINT size)
3908 {
3909 	void *ret;
3910 	// Validate arguments
3911 	if (addr == NULL)
3912 	{
3913 		return NULL;
3914 	}
3915 
3916 	ret = Malloc(size);
3917 	Copy(ret, addr, size);
3918 
3919 	return ret;
3920 }
3921 
3922 // Memory copy
Copy(void * dst,void * src,UINT size)3923 void Copy(void *dst, void *src, UINT size)
3924 {
3925 	// Validate arguments
3926 	if (dst == NULL || src == NULL || size == 0 || dst == src)
3927 	{
3928 		return;
3929 	}
3930 
3931 	// KS
3932 	KS_INC(KS_COPY_COUNT);
3933 
3934 	memcpy(dst, src, size);
3935 }
3936 
3937 // Memory move
Move(void * dst,void * src,UINT size)3938 void Move(void *dst, void *src, UINT size)
3939 {
3940 	// Validate arguments
3941 	if (dst == NULL || src == NULL || size == 0 || dst == src)
3942 	{
3943 		return;
3944 	}
3945 
3946 	// KS
3947 	KS_INC(KS_COPY_COUNT);
3948 
3949 	memmove(dst, src, size);
3950 }
3951 
3952 // Memory comparison
Cmp(void * p1,void * p2,UINT size)3953 int Cmp(void *p1, void *p2, UINT size)
3954 {
3955 	// Validate arguments
3956 	if (p1 == NULL || p2 == NULL || size == 0)
3957 	{
3958 		return 0;
3959 	}
3960 
3961 	return memcmp(p1, p2, (size_t)size);
3962 }
3963 
3964 // Memory comparison (case-insensitive)
CmpCaseIgnore(void * p1,void * p2,UINT size)3965 int CmpCaseIgnore(void *p1, void *p2, UINT size)
3966 {
3967 	UINT i;
3968 	// Validate arguments
3969 	if (p1 == NULL || p2 == NULL || size == 0)
3970 	{
3971 		return 0;
3972 	}
3973 
3974 	for (i = 0;i < size;i++)
3975 	{
3976 		char c1 = (char)(*(((UCHAR *)p1) + i));
3977 		char c2 = (char)(*(((UCHAR *)p2) + i));
3978 
3979 		c1 = ToUpper(c1);
3980 		c2 = ToUpper(c2);
3981 
3982 		if (c1 != c2)
3983 		{
3984 			return COMPARE_RET(c1, c2);
3985 		}
3986 	}
3987 
3988 	return 0;
3989 }
3990 
3991 // Zero-clear of memory
Zero(void * addr,UINT size)3992 void Zero(void *addr, UINT size)
3993 {
3994 	// Validate arguments
3995 	if (addr == NULL || size == 0)
3996 	{
3997 		return;
3998 	}
3999 
4000 	// KS
4001 	KS_INC(KS_ZERO_COUNT);
4002 
4003 	memset(addr, 0, size);
4004 }
4005 
4006 // Compare the string map entries
StrMapCmp(void * p1,void * p2)4007 int StrMapCmp(void *p1, void *p2)
4008 {
4009 	STRMAP_ENTRY *s1, *s2;
4010 	if (p1 == NULL || p2 == NULL)
4011 	{
4012 		return 0;
4013 	}
4014 	s1 = *(STRMAP_ENTRY **)p1;
4015 	s2 = *(STRMAP_ENTRY **)p2;
4016 	if (s1 == NULL || s2 == NULL)
4017 	{
4018 		return 0;
4019 	}
4020 	return StrCmpi(s1->Name, s2->Name);
4021 }
4022 
4023 // Create a string map (the data that can be searched by the string)
NewStrMap()4024 LIST *NewStrMap()
4025 {
4026 	return NewList(StrMapCmp);
4027 }
4028 
4029 // Search in string map
StrMapSearch(LIST * map,char * key)4030 void *StrMapSearch(LIST *map, char *key)
4031 {
4032 	STRMAP_ENTRY tmp, *result;
4033 	tmp.Name = key;
4034 	result = (STRMAP_ENTRY*)Search(map, &tmp);
4035 	if(result != NULL)
4036 	{
4037 		return result->Value;
4038 	}
4039 	return NULL;
4040 }
4041 
4042 // XOR the data
XorData(void * dst,void * src1,void * src2,UINT size)4043 void XorData(void *dst, void *src1, void *src2, UINT size)
4044 {
4045 	UINT i;
4046 	UCHAR *d, *c1, *c2;
4047 	// Validate arguments
4048 	if (dst == NULL || src1 == NULL || src2 == NULL || size == 0)
4049 	{
4050 		return;
4051 	}
4052 
4053 	d = (UCHAR *)dst;
4054 	c1 = (UCHAR *)src1;
4055 	c2 = (UCHAR *)src2;
4056 
4057 	for (i = 0;i < size;i++)
4058 	{
4059 		*d = (*c1) ^ (*c2);
4060 
4061 		d++;
4062 		c1++;
4063 		c2++;
4064 	}
4065 }
4066