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