1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Mayaqua Kernel
3
4
5 // Mayaqua.c
6 // Mayaqua Kernel program
7
8 #include "Mayaqua.h"
9
10 #include "Encrypt.h"
11 #include "FileIO.h"
12 #include "GlobalConst.h"
13 #include "Internat.h"
14 #include "Memory.h"
15 #include "Microsoft.h"
16 #include "Network.h"
17 #include "Object.h"
18 #include "OS.h"
19 #include "Secure.h"
20 #include "Str.h"
21 #include "Table.h"
22 #include "Tick64.h"
23 #include "Tracking.h"
24
25 #include <locale.h>
26 #include <stdlib.h>
27
28 // Global variable
29 bool g_memcheck; // Enable memory check
30 bool g_debug; // Debug mode
31 UINT64 kernel_status[NUM_KERNEL_STATUS]; // Kernel state
32 UINT64 kernel_status_max[NUM_KERNEL_STATUS]; // Kernel state (maximum value)
33 LOCK *kernel_status_lock[NUM_KERNEL_STATUS]; // Kernel state lock
34 bool kernel_status_inited = false; // Kernel state initialization flag
35 bool g_little_endian = true;
36 char *cmdline = NULL; // Command line
37 wchar_t *uni_cmdline = NULL; // Unicode command line
38 bool g_foreground = false; // Execute service in foreground mode
39
40 // Static variable
41 static char *exename = NULL; // EXE file name (ANSI)
42 static wchar_t *exename_w = NULL; // EXE file name (Unicode)
43 static TOKEN_LIST *cmdline_token = NULL; // Command line token
44 static UNI_TOKEN_LIST *cmdline_uni_token = NULL; // Command line token (Unicode)
45 static OS_INFO *os_info = NULL; // OS information
46 static bool dot_net_mode = false;
47 static bool minimal_mode = false;
48 static UINT last_time_check = 0;
49 static UINT first_time_check = 0;
50 static bool is_nt = false;
51 static bool is_ham_mode = false;
52 static UINT init_mayaqua_counter = 0;
53 static bool use_probe = false;
54 static BUF *probe_buf = NULL;
55 static LOCK *probe_lock = NULL;
56 static UINT64 probe_start = 0;
57 static UINT64 probe_last = 0;
58 static bool probe_enabled = false;
59
60 // The function which should be called once as soon as possible after the process is started
61 static bool init_proc_once_flag = false;
InitProcessCallOnce()62 void InitProcessCallOnce()
63 {
64 if (init_proc_once_flag == false)
65 {
66 init_proc_once_flag = true;
67
68 #ifdef OS_WIN32
69 MsInitProcessCallOnce();
70 #endif // OS_WIN32
71 }
72 }
73
74 // Calculate the checksum
CalcChecksum16(void * buf,UINT size)75 USHORT CalcChecksum16(void *buf, UINT size)
76 {
77 int sum = 0;
78 USHORT *addr = (USHORT *)buf;
79 int len = (int)size;
80 USHORT *w = addr;
81 int nleft = len;
82 USHORT answer = 0;
83
84 while (nleft > 1)
85 {
86 USHORT ww = 0;
87 Copy(&ww, w++, sizeof(USHORT));
88 sum += ww;
89 nleft -= 2;
90 }
91
92 if (nleft == 1)
93 {
94 *(UCHAR *)(&answer) = *(UCHAR *)w;
95 sum += answer;
96 }
97
98 sum = (sum >> 16) + (sum & 0xffff);
99 sum += (sum >> 16);
100
101 answer = ~sum;
102
103 return answer;
104 }
105
106 // Writing a probe with the data
WriteProbeData(char * filename,UINT line,char * str,void * data,UINT size)107 void WriteProbeData(char *filename, UINT line, char *str, void *data, UINT size)
108 {
109 char tmp[MAX_SIZE];
110 USHORT cs;
111
112 if (IsProbeEnabled() == false)
113 {
114 return;
115 }
116
117 // Take a checksum of the data
118 if (size != 0)
119 {
120 cs = CalcChecksum16(data, size);
121 }
122 else
123 {
124 cs = 0;
125 }
126
127 // Generating a String
128 snprintf(tmp, sizeof(tmp), "\"%s\" (Size=%5u, Crc=0x%04X)", str, size, cs);
129
130 WriteProbe(filename, line, tmp);
131 }
132
133 // Writing Probe
WriteProbe(char * filename,UINT line,char * str)134 void WriteProbe(char *filename, UINT line, char *str)
135 {
136 #ifdef OS_WIN32
137 char *s;
138 char tmp[MAX_SIZE];
139 char tmp2[MAX_SIZE];
140 UINT64 now = 0;
141 UINT64 time;
142
143 if (IsProbeEnabled() == false)
144 {
145 return;
146 }
147
148 now = MsGetHiResCounter();
149
150 Lock(probe_lock);
151 {
152 UINT64 diff;
153
154 time = MsGetHiResTimeSpanUSec(now - probe_start);
155
156 diff = time - probe_last;
157
158 if (time < probe_last)
159 {
160 diff = 0;
161 }
162
163 probe_last = time;
164
165 ToStr64(tmp, time);
166 MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
167 WriteBuf(probe_buf, tmp2, StrLen(tmp2));
168 WriteBuf(probe_buf, tmp, StrLen(tmp));
169
170 s = " [+";
171 WriteBuf(probe_buf, s, StrLen(s));
172
173 ToStr64(tmp, diff);
174 MakeCharArray2(tmp2, ' ', (UINT)(MIN(12, (int)12 - (int)StrLen(tmp))));
175 WriteBuf(probe_buf, tmp2, StrLen(tmp2));
176 WriteBuf(probe_buf, tmp, StrLen(tmp));
177
178 s = "] - ";
179 WriteBuf(probe_buf, s, StrLen(s));
180
181 WriteBuf(probe_buf, filename, StrLen(filename));
182
183 s = "(";
184 WriteBuf(probe_buf, s, StrLen(s));
185
186 ToStr64(tmp, (UINT64)line);
187 WriteBuf(probe_buf, tmp, StrLen(tmp));
188
189 s = "): ";
190 WriteBuf(probe_buf, s, StrLen(s));
191
192 WriteBuf(probe_buf, str, StrLen(str));
193
194 s = "\r\n";
195 WriteBuf(probe_buf, s, StrLen(s));
196 }
197 Unlock(probe_lock);
198 #endif // OS_WIN32
199 }
200
201 // Initialization of Probe
InitProbe()202 void InitProbe()
203 {
204 probe_buf = NewBuf();
205 probe_lock = NewLock();
206 probe_enabled = false;
207
208 probe_start = 0;
209
210 #ifdef OS_WIN32
211 probe_start = MsGetHiResCounter();
212 #endif // OS_WIN32
213 }
214
215 // Release of Probe
FreeProbe()216 void FreeProbe()
217 {
218 if (probe_buf->Size >= 1)
219 {
220 SYSTEMTIME st;
221 char filename[MAX_SIZE];
222
223 // Write all to the file
224 MakeDirEx("@probe_log");
225
226 LocalTime(&st);
227
228 snprintf(filename, sizeof(filename), "@probe_log/%04u%02u%02u_%02u%02u%02u.log",
229 st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
230
231 DumpBuf(probe_buf, filename);
232 }
233
234 FreeBuf(probe_buf);
235 DeleteLock(probe_lock);
236 }
237
238 // Set enable / disable the Probe
EnableProbe(bool enable)239 void EnableProbe(bool enable)
240 {
241 probe_enabled = enable;
242 }
243
244 // Get whether the Probe is enabled?
IsProbeEnabled()245 bool IsProbeEnabled()
246 {
247 #ifndef USE_PROBE
248 return false;
249 #else // USE_PROBE
250 return probe_enabled;
251 #endif // USE_PROBE
252 }
253
254 // Set the Ham mode
SetHamMode()255 void SetHamMode()
256 {
257 is_ham_mode = true;
258 }
259
260 // Get whether in Ham mode
IsHamMode()261 bool IsHamMode()
262 {
263 return is_ham_mode;
264 }
265
266 // Display the time from the previous call to now
TimeCheck()267 void TimeCheck()
268 {
269 #ifdef OS_WIN32
270 UINT now, ret, total;
271 now = Win32GetTick();
272 if (last_time_check == 0)
273 {
274 ret = 0;
275 }
276 else
277 {
278 ret = now - last_time_check;
279 }
280 last_time_check = now;
281
282 if (first_time_check == 0)
283 {
284 first_time_check = now;
285 }
286
287 total = now - first_time_check;
288
289 printf(" -- %3.3f / %3.3f\n", (double)ret / 1000.0f, (double)total / 1000.0f);
290 #endif // OS_WIN32
291 }
292
293 // Whether this system is IA64
IsIA64()294 bool IsIA64()
295 {
296 if (Is64() == false)
297 {
298 return false;
299 }
300
301 #ifndef MAYAQUA_IA_64
302 return false;
303 #else // MAYAQUA_IA_64
304 return true;
305 #endif // MAYAQUA_IA_64
306 }
307
308 // Whether in x64
IsX64()309 bool IsX64()
310 {
311 if (Is64() == false)
312 {
313 return false;
314 }
315
316 #ifndef MAYAQUA_IA_64
317 return true;
318 #else // MAYAQUA_IA_64
319 return false;
320 #endif // MAYAQUA_IA_64
321 }
322
323 // Whether 64bit
Is64()324 bool Is64()
325 {
326 #ifdef CPU_64
327 return true;
328 #else // CPU_64
329 return false;
330 #endif // CPU_64
331 }
332
333 // Whether 32bit
Is32()334 bool Is32()
335 {
336 return Is64() ? false : true;
337 }
338
339 // Acquisition whether in .NET mode
MayaquaIsDotNetMode()340 bool MayaquaIsDotNetMode()
341 {
342 return dot_net_mode;
343 }
344
345 // Check the endian
CheckEndian()346 void CheckEndian()
347 {
348 unsigned short test;
349 UCHAR *buf;
350
351 test = 0x1234;
352 buf = (UCHAR *)&test;
353 if (buf[0] == 0x12)
354 {
355 g_little_endian = false;
356 }
357 else
358 {
359 g_little_endian = true;
360 }
361 }
362
363 // Minimize mode
MayaquaMinimalMode()364 void MayaquaMinimalMode()
365 {
366 minimal_mode = true;
367 }
MayaquaIsMinimalMode()368 bool MayaquaIsMinimalMode()
369 {
370 return minimal_mode;
371 }
372
373 // Whether in NT
IsNt()374 bool IsNt()
375 {
376 return is_nt;
377 }
378
379 // Initialization of Mayaqua library
InitMayaqua(bool memcheck,bool debug,int argc,char ** argv)380 void InitMayaqua(bool memcheck, bool debug, int argc, char **argv)
381 {
382 wchar_t tmp[MAX_PATH];
383 UCHAR hash[SHA1_SIZE];
384
385 if ((init_mayaqua_counter++) > 0)
386 {
387 return;
388 }
389
390 InitProcessCallOnce();
391
392 g_memcheck = memcheck;
393 g_debug = debug;
394 cmdline = NULL;
395 if (dot_net_mode == false)
396 {
397 // Fail this for some reason when this is called this in .NET mode
398 setbuf(stdout, NULL);
399 }
400
401 #ifdef OS_UNIX
402 g_foreground = (argc >= 3 && StrCmpi(argv[2], UNIX_SVC_ARG_FOREGROUND) == 0);
403 #else
404 g_foreground = false;
405 #endif // OS_UNIX
406
407 // Acquisition whether NT
408 #ifdef OS_WIN32
409 is_nt = Win32IsNt();
410 #endif // OS_WIN32
411
412 // Check endian
413 CheckEndian();
414
415 #ifdef OS_WIN32
416 _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
417 #endif // OS_WIN32
418
419 // Set the locale information of the CRT to the Japanese
420 setlocale(LC_ALL, "");
421
422 // Initialization of OS
423 OSInit();
424
425 // Initialize the random number
426 srand((UINT)SystemTime64());
427
428 tick_manual_lock = NewLock();
429
430 // Initialization of CRC32
431 InitCrc32();
432
433 // Initialization of the FIFO system
434 InitFifo();
435
436 // Initialize the Kernel status
437 InitKernelStatus();
438
439 if (IsTrackingEnabled())
440 {
441 // Initialize the tracking
442 InitTracking();
443 }
444
445 // Initialization of thread pool
446 InitThreading();
447
448 // Initialize the string library
449 InitStringLibrary();
450
451 // Initialization of the locale information
452 SetLocale(NULL);
453
454 // Initialization of the crypt library
455 InitCryptLibrary();
456
457 // Initialization of the real-time clock
458 InitTick64();
459
460 // Initialize the network communication module
461 InitNetwork();
462
463 // Initialization of the acquisition of the EXE file name
464 InitGetExeName(argc >= 1 ? argv[0] : NULL);
465
466 // Initialization of the command line string
467 InitCommandLineStr(argc, argv);
468
469 // Initialization of OS information
470 InitOsInfo();
471
472 // Initialization of the operating system-specific module
473 #ifdef OS_WIN32
474 MsInit(); // Microsoft Win32
475 #endif // OS_WIN32
476
477 // Initialization of the security token module
478 InitSecure();
479
480 if (OSIsSupportedOs() == false)
481 {
482 // Abort
483 exit(0);
484 }
485
486 // RSA Check
487 if (RsaCheckEx() == false)
488 {
489 // Abort
490 Alert("OpenSSL Library Init Failed. (too old?)\nPlease install the latest version of OpenSSL.\n\n", "RsaCheck()");
491 exit(0);
492 }
493
494 // Initialization of HamCore file system
495 InitHamcore();
496
497 // Initialization of string table routine
498 InitTable();
499
500 if (exename == NULL)
501 {
502 // Executable file name
503 exename = CopyStr("unknown");
504 }
505
506 // Check whether the executable file name of themselves is found
507 // (If not found, quit because this is started in strange path)
508 GetExeNameW(tmp, sizeof(tmp));
509 if (IsFileExistsW(tmp) == false)
510 {
511 wchar_t tmp2[MAX_SIZE];
512
513 UniFormat(tmp2, sizeof(tmp2),
514 L"Error: Executable binary file \"%s\" not found.\r\n\r\n"
515 L"Please execute program with full path.\r\n",
516 tmp);
517
518 AlertW(tmp2, NULL);
519 _exit(0);
520 }
521
522 CheckUnixTempDir();
523
524 // Initialization of Probe
525 InitProbe();
526
527 // Initialization of Machine Hash
528 GetCurrentMachineIpProcessHash(hash);
529
530 // Reading Private IP file
531 LoadPrivateIPFile();
532 }
533
534 // Release of Mayaqua library
FreeMayaqua()535 void FreeMayaqua()
536 {
537 if ((--init_mayaqua_counter) > 0)
538 {
539 return;
540 }
541
542 // Release of Private IP File
543 FreePrivateIPFile();
544
545 // Release of Probe
546 FreeProbe();
547
548 // Delete the table
549 FreeTable();
550
551 // Release of security token module
552 FreeSecure();
553
554 // Release of the operating system specific module
555 #ifdef OS_WIN32
556 MsFree();
557 #endif // OS_WIN32
558
559 // Release of OS information
560 FreeOsInfo();
561
562 // Release of HamCore file system
563 FreeHamcore();
564
565 // Release of the command line string
566 FreeCommandLineStr();
567
568 // Release of the command line token
569 FreeCommandLineTokens();
570
571 // Release of network communication module
572 FreeNetwork();
573
574 // Release of real-time clock
575 FreeTick64();
576
577 // Release of the string library
578 FreeStringLibrary();
579
580 // Release of thread pool
581 FreeThreading();
582
583 // Release of crypt library
584 FreeCryptLibrary();
585
586 if (IsTrackingEnabled())
587 {
588 // Show the kernel status
589 if (g_debug)
590 {
591 PrintKernelStatus();
592 }
593
594 // Display the debug information
595 if (g_memcheck)
596 {
597 PrintDebugInformation();
598 }
599
600 // Release the tracking
601 FreeTracking();
602 }
603
604 // Release of the kernel status
605 FreeKernelStatus();
606
607 DeleteLock(tick_manual_lock);
608 tick_manual_lock = NULL;
609
610 // Release of OS
611 OSFree();
612 }
613
614 // Check whether /tmp is available in the UNIX
CheckUnixTempDir()615 void CheckUnixTempDir()
616 {
617 if (OS_IS_UNIX(GetOsInfo()->OsType))
618 {
619 char tmp[128], tmp2[64];
620 UINT64 now = SystemTime64();
621 IO *o;
622
623 MakeDir("/tmp");
624
625 Format(tmp2, sizeof(tmp2), "%I64u", now);
626
627 Format(tmp, sizeof(tmp), "/tmp/.%s", tmp2);
628
629 o = FileCreate(tmp);
630 if (o == NULL)
631 {
632 o = FileOpen(tmp, false);
633 if (o == NULL)
634 {
635 Print("Unable to use /tmp.\n\n");
636 exit(0);
637 }
638 }
639
640 FileClose(o);
641
642 FileDelete(tmp);
643 }
644 }
645
646 // Show an alert
Alert(char * msg,char * caption)647 void Alert(char *msg, char *caption)
648 {
649 OSAlert(msg, caption);
650 }
AlertW(wchar_t * msg,wchar_t * caption)651 void AlertW(wchar_t *msg, wchar_t *caption)
652 {
653 OSAlertW(msg, caption);
654 }
655
656 // Get the OS type
GetOsType()657 UINT GetOsType()
658 {
659 OS_INFO *i = GetOsInfo();
660
661 if (i == NULL)
662 {
663 return 0;
664 }
665
666 return i->OsType;
667 }
668
669 // Getting OS information
GetOsInfo()670 OS_INFO *GetOsInfo()
671 {
672 return os_info;
673 }
674
675 // Initialization of OS information
InitOsInfo()676 void InitOsInfo()
677 {
678 if (os_info != NULL)
679 {
680 return;
681 }
682
683 os_info = ZeroMalloc(sizeof(OS_INFO));
684
685 OSGetOsInfo(os_info);
686 }
687
688 // Release of OS information
FreeOsInfo()689 void FreeOsInfo()
690 {
691 if (os_info == NULL)
692 {
693 return;
694 }
695
696 Free(os_info->OsSystemName);
697 Free(os_info->OsProductName);
698 Free(os_info->OsVendorName);
699 Free(os_info->OsVersion);
700 Free(os_info->KernelName);
701 Free(os_info->KernelVersion);
702 Free(os_info);
703
704 os_info = NULL;
705 }
706
707 // Get the Unicode command line tokens
GetCommandLineUniToken()708 UNI_TOKEN_LIST *GetCommandLineUniToken()
709 {
710 if (cmdline_uni_token == NULL)
711 {
712 return UniNullToken();
713 }
714 else
715 {
716 return UniCopyToken(cmdline_uni_token);
717 }
718 }
719
720 // Getting the command line tokens
GetCommandLineToken()721 TOKEN_LIST *GetCommandLineToken()
722 {
723 if (cmdline_token == NULL)
724 {
725 return NullToken();
726 }
727 else
728 {
729 return CopyToken(cmdline_token);
730 }
731 }
732
733 // Convert the command line string into tokens
ParseCommandLineTokens()734 void ParseCommandLineTokens()
735 {
736 if (cmdline_token != NULL)
737 {
738 FreeToken(cmdline_token);
739 }
740 cmdline_token = ParseCmdLine(cmdline);
741
742 if (cmdline_uni_token != NULL)
743 {
744 UniFreeToken(cmdline_uni_token);
745 }
746 cmdline_uni_token = UniParseCmdLine(uni_cmdline);
747 }
748
749 // Release command line tokens
FreeCommandLineTokens()750 void FreeCommandLineTokens()
751 {
752 if (cmdline_token != NULL)
753 {
754 FreeToken(cmdline_token);
755 }
756 cmdline_token = NULL;
757
758 if (cmdline_uni_token != NULL)
759 {
760 UniFreeToken(cmdline_uni_token);
761 }
762 cmdline_uni_token = NULL;
763 }
764
765 // Initialization of the command line string
InitCommandLineStr(int argc,char ** argv)766 void InitCommandLineStr(int argc, char **argv)
767 {
768 if (argc >= 1)
769 {
770 #ifdef OS_UNIX
771 exename_w = CopyUtfToUni(argv[0]);
772 exename = CopyUniToStr(exename_w);
773 #else // OS_UNIX
774 exename = CopyStr(argv[0]);
775 exename_w = CopyStrToUni(exename);
776 #endif // OS_UNIX
777 }
778 if (argc < 2 || argv == NULL)
779 {
780 // No command-line string
781 SetCommandLineStr(NULL);
782 }
783 else
784 {
785 // There are command-line string
786 int i, total_len = 1;
787 char *tmp;
788
789 for (i = 1;i < argc;i++)
790 {
791 total_len += StrLen(argv[i]) * 2 + 32;
792 }
793 tmp = ZeroMalloc(total_len);
794
795 for (i = 1;i < argc;i++)
796 {
797 UINT s_size = StrLen(argv[i]) * 2;
798 char *s = ZeroMalloc(s_size);
799 bool dq = (SearchStrEx(argv[i], " ", 0, true) != INFINITE);
800 ReplaceStrEx(s, s_size, argv[i], "\"", "\"\"", true);
801 if (dq)
802 {
803 StrCat(tmp, total_len, "\"");
804 }
805 StrCat(tmp, total_len, s);
806 if (dq)
807 {
808 StrCat(tmp, total_len, "\"");
809 }
810 StrCat(tmp, total_len, " ");
811 Free(s);
812 }
813
814 Trim(tmp);
815 SetCommandLineStr(tmp);
816 Free(tmp);
817 }
818 }
819
820 // Release of the command line string
FreeCommandLineStr()821 void FreeCommandLineStr()
822 {
823 SetCommandLineStr(NULL);
824
825 if (exename != NULL)
826 {
827 Free(exename);
828 exename = NULL;
829 }
830
831 if (exename_w != NULL)
832 {
833 Free(exename_w);
834 exename_w = NULL;
835 }
836 }
837
838 // Get the Unicode command line string
GetCommandLineUniStr()839 wchar_t *GetCommandLineUniStr()
840 {
841 if (uni_cmdline == NULL)
842 {
843 return UniCopyStr(L"");
844 }
845 else
846 {
847 return UniCopyStr(uni_cmdline);
848 }
849 }
850
851 // Get the command line string
GetCommandLineStr()852 char *GetCommandLineStr()
853 {
854 if (cmdline == NULL)
855 {
856 return CopyStr("");
857 }
858 else
859 {
860 return CopyStr(cmdline);
861 }
862 }
863
864 // Set the Unicode command line string
SetCommandLineUniStr(wchar_t * str)865 void SetCommandLineUniStr(wchar_t *str)
866 {
867 if (uni_cmdline != NULL)
868 {
869 Free(uni_cmdline);
870 }
871 if (str == NULL)
872 {
873 uni_cmdline = NULL;
874 }
875 else
876 {
877 uni_cmdline = CopyUniStr(str);
878 }
879
880 ParseCommandLineTokens();
881 }
882
883 // Set the command-line string
SetCommandLineStr(char * str)884 void SetCommandLineStr(char *str)
885 {
886 // Validate arguments
887 if (str == NULL)
888 {
889 if (cmdline != NULL)
890 {
891 Free(cmdline);
892 }
893 cmdline = NULL;
894 }
895 else
896 {
897 if (cmdline != NULL)
898 {
899 Free(cmdline);
900 }
901 cmdline = CopyStr(str);
902 }
903
904 if (cmdline == NULL)
905 {
906 if (uni_cmdline != NULL)
907 {
908 Free(uni_cmdline);
909 uni_cmdline = NULL;
910 }
911 }
912 else
913 {
914 if (uni_cmdline != NULL)
915 {
916 Free(uni_cmdline);
917 }
918 uni_cmdline = CopyStrToUni(cmdline);
919 }
920
921 ParseCommandLineTokens();
922 }
923
924 // Display the kernel status
PrintKernelStatus()925 void PrintKernelStatus()
926 {
927 bool leaked = false;
928
929 Print("\n");
930 Print(
931 " --------- Mayaqua Kernel Status ---------\n"
932 " Malloc Count ............... %u\n"
933 " ReAlloc Count .............. %u\n"
934 " Free Count ................. %u\n"
935 " Total Memory Size .......... %I64u bytes\n"
936 " * Current Memory Blocks ...... %u Blocks (Peek: %u)\n"
937 " Total Memory Blocks ........ %u Blocks\n"
938 " * Current MemPool Blocks ..... %u Blocks (Peek: %u)\n"
939 " Total MemPool Mallocs ...... %u Mallocs\n"
940 " Total MemPool ReAllocs ..... %u ReAllocs\n"
941 " NewLock Count .............. %u\n"
942 " DeleteLock Count ........... %u\n"
943 " * Current Lock Objects ....... %u Objects\n"
944 " * Current Locked Objects ..... %u Objects\n"
945 " NewRef Count ............... %u\n"
946 " FreeRef Count .............. %u\n"
947 " * Current Ref Objects ........ %u Objects\n"
948 " * Current Ref Count .......... %u Refs\n"
949 " GetTime Count .............. %u\n"
950 " GetTick Count .............. %u\n"
951 " NewThread Count ............ %u\n"
952 " FreeThread Count ........... %u\n"
953 " * Current Threads ............ %u Threads\n"
954 " Wait For Event Count ....... %u\n\n",
955 KS_GET(KS_MALLOC_COUNT),
956 KS_GET(KS_REALLOC_COUNT),
957 KS_GET(KS_FREE_COUNT),
958 KS_GET64(KS_TOTAL_MEM_SIZE),
959 KS_GET(KS_CURRENT_MEM_COUNT),
960 KS_GETMAX(KS_CURRENT_MEM_COUNT),
961 KS_GET(KS_TOTAL_MEM_COUNT),
962 KS_GET(KS_MEMPOOL_CURRENT_NUM),
963 KS_GETMAX(KS_MEMPOOL_CURRENT_NUM),
964 KS_GET(KS_MEMPOOL_MALLOC_COUNT),
965 KS_GET(KS_MEMPOOL_REALLOC_COUNT),
966 KS_GET(KS_NEWLOCK_COUNT),
967 KS_GET(KS_DELETELOCK_COUNT),
968 KS_GET(KS_CURRENT_LOCK_COUNT),
969 KS_GET(KS_CURRENT_LOCKED_COUNT),
970 KS_GET(KS_NEWREF_COUNT),
971 KS_GET(KS_FREEREF_COUNT),
972 KS_GET(KS_CURRENT_REF_COUNT),
973 KS_GET(KS_CURRENT_REFED_COUNT),
974 KS_GET(KS_GETTIME_COUNT),
975 KS_GET(KS_GETTICK_COUNT),
976 KS_GET(KS_NEWTHREAD_COUNT),
977 KS_GET(KS_FREETHREAD_COUNT),
978 KS_GET(KS_NEWTHREAD_COUNT) - KS_GET(KS_FREETHREAD_COUNT),
979 KS_GET(KS_WAIT_COUNT)
980 );
981
982 if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
983 KS_GET(KS_MEMPOOL_CURRENT_NUM) != 0 ||
984 KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
985 {
986 leaked = true;
987 }
988
989 if (leaked)
990 {
991 Print(" !!! MEMORY LEAKS DETECTED !!!\n\n");
992 if (g_memcheck == false)
993 {
994 if (IsHamMode())
995 {
996 Print(" Enable /memcheck startup option to see the leaking memory heap.\n");
997 Print(" Press Enter key to exit the process.\n");
998 }
999 GetLine(NULL, 0);
1000 }
1001 }
1002 else
1003 {
1004 Print(" @@@ NO MEMORY LEAKS @@@\n\n");
1005 }
1006 }
1007
1008 // Initialize Kernel status
InitKernelStatus()1009 void InitKernelStatus()
1010 {
1011 UINT i;
1012
1013 // Memory initialization
1014 Zero(kernel_status, sizeof(kernel_status));
1015 Zero(kernel_status_max, sizeof(kernel_status_max));
1016
1017 // Lock initialization
1018 for (i = 0;i < NUM_KERNEL_STATUS;i++)
1019 {
1020 kernel_status_lock[i] = OSNewLock();
1021 }
1022
1023 kernel_status_inited = true;
1024 }
1025
1026 // Release of the kernel status
FreeKernelStatus()1027 void FreeKernelStatus()
1028 {
1029 UINT i;
1030
1031 kernel_status_inited = false;
1032
1033 // Lock release
1034 for (i = 0;i < NUM_KERNEL_STATUS;i++)
1035 {
1036 OSDeleteLock(kernel_status_lock[i]);
1037 }
1038 }
1039
1040 // Lock the kernel status
LockKernelStatus(UINT id)1041 void LockKernelStatus(UINT id)
1042 {
1043 // Validate arguments
1044 if (id >= NUM_KERNEL_STATUS)
1045 {
1046 return;
1047 }
1048
1049 OSLock(kernel_status_lock[id]);
1050 }
1051
1052 // Unlock the kernel status
UnlockKernelStatus(UINT id)1053 void UnlockKernelStatus(UINT id)
1054 {
1055 // Validate arguments
1056 if (id >= NUM_KERNEL_STATUS)
1057 {
1058 return;
1059 }
1060
1061 OSUnlock(kernel_status_lock[id]);
1062 }
1063
1064 // Display the debug information
PrintDebugInformation()1065 void PrintDebugInformation()
1066 {
1067 MEMORY_STATUS memory_status;
1068 GetMemoryStatus(&memory_status);
1069
1070 // Header
1071 Print("====== " CEDAR_PRODUCT_STR " VPN System Debug Information ======\n");
1072
1073 // Memory information
1074 Print(" <Memory Status>\n"
1075 " Number of Allocated Memory Blocks: %u\n"
1076 " Total Size of Allocated Memory Blocks: %u bytes\n",
1077 memory_status.MemoryBlocksNum, memory_status.MemorySize);
1078
1079 // Footer
1080 Print("====================================================\n");
1081
1082 if (KS_GET(KS_CURRENT_MEM_COUNT) != 0 || KS_GET(KS_CURRENT_LOCK_COUNT) != 0 ||
1083 KS_GET(KS_CURRENT_LOCKED_COUNT) != 0 || KS_GET(KS_CURRENT_REF_COUNT) != 0)
1084 {
1085 // Show a debug menu because memory leaks suspected
1086 MemoryDebugMenu();
1087 }
1088 }
1089
1090
1091
1092
1093