spshell.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  1. #include "precompile.h"
  2. #include "app.h"
  3. #include "osutil.h"
  4. #include "version.h"
  5. #include "memtrace.h"
  6. #include "sp_def.h"
  7. #ifdef RVC_OS_WIN
  8. #include <DbgHelp.h>
  9. #include <TlHelp32.h>
  10. #include <shellapi.h>
  11. #else
  12. #include <unistd.h>
  13. #endif //RVC_OS_WIN
  14. #include "fileutil.h"
  15. #include "iniutil.h"
  16. #include "getopt.h"
  17. #include "toolkit.h"
  18. #include "SimpleString.h"
  19. #include "md5file.h"
  20. #include "SpBase.h"
  21. #include "SpComm.hpp"
  22. #ifdef RVC_OS_WIN
  23. #include <io.h>
  24. #pragma comment(lib, "dbghelp.lib")
  25. #else
  26. #include <unistd.h>
  27. #include <sys/syscall.h>
  28. #endif //RVC_OS_WIN
  29. #include <map>
  30. #include <iterator>
  31. #include <fstream>
  32. #include "libtoolkit/log.h"
  33. #include <signal.h>
  34. #include "SpBase.h"
  35. #include "sp_dbg_export.h"
  36. #include "versionBase.h"
  37. #include "base64File.hpp"
  38. #include "RVCEventCode.h"
  39. #include "dbgutil.h"
  40. #include <locale.h>
  41. #include <winpr/library.h>
  42. #include <winpr/environment.h>
  43. #include <winpr/registry.h>
  44. #include <winpr/sysinfo.h>
  45. #ifdef realloc
  46. #undef realloc //(p, s)
  47. #endif
  48. using namespace std;
  49. #include <spbase/sp_runTask.h>
  50. #ifndef RVC_OS_WIN
  51. static int GetParentProcessID()
  52. {
  53. #if 0
  54. return getppid();
  55. #else
  56. return (int)syscall(SYS_getppid);
  57. #endif
  58. }
  59. #endif //NOT _WIN32
  60. #ifdef RVC_OS_WIN
  61. static char spshell_execute_name[] = "SpShell.exe";
  62. static char sphost_execute_name[] = "SpHost.exe";
  63. static char guardian_execute_name[] = "Guardian.exe";
  64. static char cefclient_execute_name[] = "cefclient.exe";
  65. #else
  66. static char spshell_execute_name[] = "spshell";
  67. static char sphost_execute_name[] = "sphost";
  68. static char guardian_execute_name[] = "guardian";
  69. static char cefclient_execute_name[] = "cefclient";
  70. #endif //_WIN32
  71. #define RESTART_MODE_DEFAULT 0
  72. #define RESTART_MODE_NORMAL 1
  73. #define RESTART_MODE_PRE 2
  74. #define RESTART_MODE_SHUTDOWN 3
  75. #define RESTART_MODE_POWEROFF 4
  76. #define RESTART_MODE_REBOOT 5
  77. #define DRIVER_NAME "HelloDDK"
  78. #define DRIVER_PATH "InterceptDll.sys"
  79. #define SET_EVENT \
  80. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  81. #define GET_SHARE_ADD \
  82. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
  83. HANDLE g_hEvent = NULL;
  84. bool g_bMD5Exist = false;
  85. bool g_bWow64 = false;
  86. CSimpleStringA g_strMD5ListPath;
  87. static int g_restartMode = RESTART_MODE_DEFAULT;
  88. static bool g_immediately = false;
  89. char* relate_processes[] = { spshell_execute_name, sphost_execute_name, cefclient_execute_name };
  90. const int relate_processes_count = 3;
  91. char* relate_processes_ex[] = { spshell_execute_name, sphost_execute_name, guardian_execute_name, cefclient_execute_name };
  92. const int relate_processes_ex_count = 4;
  93. const int MAX_LEN = 256;
  94. //E:\Run\version\3.10.0.1\dep;E:\Run\version\3.10.0.1\bin;E:\Run\version\3.10.0.1\dev;E:\Run\version\3.10.0.1\imdep
  95. static bool IsSpPathType(const CSimpleStringA& value, const char* key)
  96. {
  97. const int leastLength = strlen("Run//1.0.0.0/") + strlen(key);
  98. CSimpleStringA path(value.GetData());
  99. if (path.IsNullOrEmpty() || path.GetLength() < leastLength) return false;
  100. for (int i = 0; i < path.GetLength(); ++i) {
  101. if (path[i] >= 'A' && path[i] <= 'Z') path[i] = path[i] + ('a' - 'A');
  102. }
  103. const int sionPos = path.IndexOf(key);
  104. const int verPos = sionPos + strlen(key) + strlen(SPLIT_SLASH_STR);
  105. if (sionPos < 0) return false;
  106. int suffixPos = -1, i;
  107. int dotCnt = 0;
  108. bool lastIsNum = false;
  109. for (i = verPos; i < path.GetLength() && (path[i] >= '0' && path[i] <= '9' || path[i] == '.'); ++i) {
  110. lastIsNum = !(path[i] == '.');
  111. if (!lastIsNum) dotCnt++;
  112. }
  113. //if (i == path.GetLength() && dotCnt == 3 && lastIsNum) return true; //D:\Run\version\3.7.1.0
  114. if (i >= path.GetLength() || dotCnt != 3 || !lastIsNum)
  115. return false;
  116. return true;
  117. }
  118. static CSimpleStringA CutSpPathFromPathValue(const char* value, const char* prefix)
  119. {
  120. CSimpleStringA path(value);
  121. CSimpleStringA result(true);
  122. CAutoArray<CSimpleStringA> values = path.Split(ENV_SEP_CHAR);
  123. if (values.GetCount() <= 0) {
  124. return path;
  125. }
  126. for (int i = 0; i < values.GetCount(); ++i) {
  127. if (!values[i].IsStartWith(prefix) && !IsSpPathType(values[i], "version") &&! IsSpPathType(values[i], "dep")) {
  128. if (!result.IsNullOrEmpty()) result += ENV_SEP_STR;
  129. result += values[i];
  130. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("toadd:%s", values[i].GetData());
  131. }
  132. }
  133. //if (!result.IsNullOrEmpty() && path[path.GetLength() - 1] == ENV_SEP_CHAR) {
  134. // result += ENV_SEP_STR;
  135. //}
  136. return result;
  137. }
  138. static void ResetEnvPath()
  139. {
  140. char path[MAX_PATH];
  141. char *buf;
  142. DWORD size;
  143. #if defined(_MSC_VER)
  144. const char* name = "PATH";
  145. #else
  146. const char* name = "LD_LIBRARY_PATH";
  147. #endif //_MSC_VER
  148. // set current path
  149. GetModuleFileNameA(NULL, path, MAX_PATH);
  150. *strrchr(path, SPLIT_SLASH) = 0; //bin
  151. *strrchr(path, SPLIT_SLASH) = 0; //1.2.3.4
  152. SetCurrentDirectoryA(path);
  153. size = GetEnvironmentVariableA(name, NULL, 0);
  154. buf = (char*)malloc(size+MAX_PATH*3);
  155. size = GetEnvironmentVariableA(name, buf, size);
  156. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("origin path:%s", buf);
  157. CSimpleStringA newValue = CutSpPathFromPathValue(buf, path);
  158. memset(buf, 0, size + MAX_PATH * 3);
  159. size = newValue.GetLength();
  160. if (!newValue.IsNullOrEmpty()) {
  161. strcpy(buf, newValue.GetData());
  162. strcat(buf, ENV_SEP_STR);
  163. }
  164. // append bin sub dir to %PATH%
  165. strcat(path, SPLIT_SLASH_STR "bin");
  166. strcat(buf, path);
  167. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("new path:%s", buf);
  168. SetEnvironmentVariableA(name, buf);
  169. free(buf);
  170. SetEnvironmentVariableA("ModuleName", "SpShell");
  171. }
  172. #ifdef RVC_OS_WIN
  173. static void SetWorkingSet()
  174. {
  175. SIZE_T dwMinSize, dwMaxSize;
  176. HANDLE hCurrProcess = GetCurrentProcess();
  177. GetProcessWorkingSetSize(hCurrProcess, &dwMinSize, &dwMaxSize);
  178. if (dwMaxSize < (2 << 20))
  179. dwMaxSize = 2 << 20;
  180. SetProcessWorkingSetSize(hCurrProcess, dwMinSize, dwMaxSize);
  181. }
  182. static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo)
  183. {
  184. static bool hasCall = false;
  185. if (hasCall)
  186. ExitProcess(Error_Exception);
  187. else
  188. hasCall = true;
  189. char tmp[MAX_PATH];
  190. HANDLE hDumpFile;
  191. std::string dmpFileStr;
  192. GetModuleFileNameA(NULL, tmp, MAX_PATH);
  193. *strrchr(tmp, SPLIT_SLASH) = 0;
  194. *strrchr(tmp, SPLIT_SLASH) = 0;
  195. *strrchr(tmp, SPLIT_SLASH) = 0;
  196. *strrchr(tmp, SPLIT_SLASH) = 0;
  197. *strrchr(tmp, SPLIT_SLASH) = 0;
  198. wsprintfA(tmp, "%s\\rvc\\dmp\\expt.spshell.%d.%s.dmp", tmp, GetCurrentProcessId(), STRFILEVER);
  199. hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE,
  200. 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  201. if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) )
  202. {
  203. MINIDUMP_EXCEPTION_INFORMATION mdei;
  204. MINIDUMP_TYPE mdt;
  205. mdei.ThreadId = GetCurrentThreadId();
  206. mdei.ExceptionPointers = ExceptionInfo;
  207. mdei.ClientPointers = FALSE;
  208. mdt = MiniDumpNormal;
  209. MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
  210. hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 );
  211. CloseHandle( hDumpFile );
  212. }
  213. char szCmd[256];
  214. sprintf_s(szCmd, 256, "TASKKILL /f /im sphost.exe");
  215. system(szCmd);
  216. sprintf_s(szCmd, 256, "TASKKILL /f /im sphost_re.exe");
  217. system(szCmd);
  218. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setLogCode(ERR_SPSHELL_EXCETION).setResultCode(RTAERR_SPSHELL_EXCEPTION)("spshell exit exception, saveDmp, %s, detail:%d:%s"
  219. , tmp, dmpFileStr.length() ,dmpFileStr.c_str());
  220. ExitProcess(Error_Exception); // exit process to suppress reporting exception
  221. return EXCEPTION_EXECUTE_HANDLER;
  222. }
  223. __declspec(dllimport) bool DisableCharmbar();
  224. __declspec(dllimport) bool EnableCharmbar();
  225. static void AutoHideTaskBar(bool bHide)
  226. {
  227. APPBARDATA apBar;
  228. memset(&apBar, 0, sizeof(apBar));
  229. apBar.cbSize = sizeof(apBar);
  230. apBar.lParam = bHide ? ABS_AUTOHIDE : ABS_ALWAYSONTOP;
  231. apBar.hWnd = FindWindow("Shell_TrayWnd", NULL);
  232. if (apBar.hWnd != NULL)
  233. {
  234. SHAppBarMessage(ABM_SETSTATE, &apBar);
  235. }
  236. }
  237. static bool AddFirewallRules()
  238. {
  239. char szBinDir[MAX_PATH] = {};
  240. GetModuleFileNameA(NULL, szBinDir, MAX_PATH);
  241. *strrchr(szBinDir, SPLIT_SLASH) = 0;
  242. int nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  243. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  244. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpHost\"\"", NULL, SW_HIDE);
  245. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpGuardian\"\"", NULL, SW_HIDE);
  246. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"cefclient\"\"", NULL, SW_HIDE);
  247. char szParam[1024] = {};
  248. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpShell\"\" dir=out program=\"\"%s\\spshell.exe\"\" action=allow\"", szBinDir);
  249. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  250. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpHost\"\" dir=out program=\"\"%s\\sphost.exe\"\" action=allow\"", szBinDir);
  251. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  252. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpHost_re\"\" dir=out program=\"\"%s\\sphost_re.exe\"\" action=allow\"", szBinDir);
  253. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  254. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpGuardian\"\" dir=out program=\"\"%s\\guardian.exe\"\" action=allow\"", szBinDir);
  255. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  256. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"cefclient\"\" dir=out program=\"\"%s\\Chromium\\cefclient.exe\"\" action=allow\"", szBinDir);
  257. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  258. return nRet > 32;
  259. }
  260. int AddFireAddFirewallRulesThread(void* param)
  261. {
  262. if (!AddFirewallRules())
  263. {
  264. DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("设置Windows防火墙策略失败!!!");
  265. Sleep(10000);
  266. return -1;
  267. }
  268. else
  269. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("设置Windows防火墙策略成功!!!");
  270. return 0;
  271. }
  272. static void AddFirewallRulesEx()
  273. {
  274. CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)& AddFireAddFirewallRulesThread, NULL, 0, NULL));
  275. }
  276. #endif //RVC_OS_WIN
  277. /*!
  278. * at Linux, judge whether current process runs as root privilege.
  279. * @return : True only if run as admin or root
  280. */
  281. static bool IsProcessRunAsAdmin()
  282. {
  283. BOOL bAdmin = FALSE;
  284. #ifdef RVC_OS_WIN
  285. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  286. PSID AdministratorsGroup = NULL;
  287. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start AllocateAndInitializeSid");
  288. if (AllocateAndInitializeSid(
  289. &NtAuthority,
  290. 2,
  291. SECURITY_BUILTIN_DOMAIN_RID,
  292. DOMAIN_ALIAS_RID_ADMINS,
  293. 0, 0, 0, 0, 0, 0,
  294. &AdministratorsGroup))
  295. {
  296. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start CheckTokenMembership");
  297. CheckTokenMembership(NULL, AdministratorsGroup, &bAdmin);
  298. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start FreeSid");
  299. FreeSid(AdministratorsGroup);
  300. }
  301. #else
  302. if (geteuid() == 0) {
  303. bAdmin = TRUE;
  304. } else {
  305. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("current process is not run as root privilege, euid:%u, uid:%d", geteuid(), getuid());
  306. }
  307. #endif //RVC_OS_WIN
  308. return bAdmin == TRUE;
  309. }
  310. const char *GetMachineType()
  311. {
  312. auto env = sp_get_env();
  313. if (env == NULL)
  314. {
  315. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("sp_get_env return null");
  316. return NULL;
  317. }
  318. return env->cfg->root_ini->machine_type;
  319. }
  320. #ifdef RVC_OS_WIN
  321. const char *GetCenterSettingNameBySite(const char *pszSite)
  322. {
  323. ///*TODO(80374374@3/23/2023): CenterSettings */
  324. #if defined(_MSC_VER)
  325. return "CenterSetting.ini";
  326. #else
  327. if (pszSite == NULL || strlen(pszSite) == 0)
  328. return "CenterSetting.ini";
  329. if ((stricmp(pszSite, "CMB.LIB") == 0)
  330. || (stricmp(pszSite, "CMB.SSB") == 0)) {
  331. return "CenterSetting.LAN.ini";
  332. } else if ((stricmp(pszSite, "CMB.LSS") == 0)
  333. || (stricmp(pszSite, "CMB.FLB") == 0)
  334. || (stricmp(pszSite, "CMB.OSB") == 0)
  335. || (stricmp(pszSite, "CMB.SMM") == 0)) {
  336. return "CenterSetting.DMZ.ini";
  337. } else {
  338. return "CenterSetting.DMZ.ini";
  339. }
  340. #endif //_MSC_VER
  341. }
  342. #endif //RVC_OS_WIN
  343. static bool SpTerminateProcess(HANDLE hProc, DWORD dwProcID)
  344. {
  345. if (!TerminateProcess(hProc, -1))
  346. {
  347. #ifdef RVC_OS_WIN
  348. char szCmd[256];
  349. int nRet = 0;
  350. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate process %d fail: 0x%X, retry with taskkill", dwProcID, GetLastError());
  351. sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", dwProcID);
  352. WinExec(szCmd, SW_HIDE);
  353. return nRet != -1;
  354. #else
  355. return false;
  356. #endif //RVC_OS_WIN
  357. }
  358. return true;
  359. }
  360. void DisplayUsage()
  361. {
  362. char szHelp[4097] = { '\0' };
  363. sprintf_s(szHelp, 4096, "\n"
  364. "Usage spshell [--entity {EntityName}][--guardian][--test][--benchmark][--kill][--debug][--ipc <pipe|tcp>][--restart][--noroot]\n"
  365. "--entity {EntityName} --启动特定的实体,选项后面输入实体名称\n"
  366. "--guardian --以后台进程的方式运行,暂未实现\n"
  367. "--test --以测试模式运行\n"
  368. "--autotest --自动化验证\n"
  369. "--debug --以调试模式运行,输出更为详细的日志\n"
  370. "--benchmark --以压力测试的模式启动\n"
  371. "--kill --直接杀死终端相关进程,比如 spshell, sphost 等\n"
  372. "--shutdown --彻底退出终端相关进程,不单独使用\n"
  373. "--systemoff --执行系统关机指令,关机前会彻底退出应用,不单独使用\n"
  374. "--reboot --执行系统重启指令,重启关机前会彻底退出应用,不单独使用\n"
  375. "--ipc <pipe|tcp> --指定实体间的通讯方式,使用管道或TCP,默认使用管道\n"
  376. "--noroot -- 允许以非管理员或Root权限方式启动\n"
  377. "--restart --重启当前应用\n"
  378. "--version --显示当前的版本\n"
  379. #ifdef WITH_DEBUG
  380. "--telnet {listern port} --激活远程调用功能\n"
  381. #endif
  382. );
  383. #ifdef RVC_OS_WIN
  384. MessageBoxA(NULL, szHelp, "Spshell Usage Tip", MB_OK);
  385. #else
  386. printf("%s\n", szHelp);
  387. #endif
  388. }
  389. static void DestroyArgs(sp_cfg_start_args_t* args)
  390. {
  391. if (args != NULL) {
  392. FREE(args->program);
  393. FREE(args->arguments);
  394. }
  395. FREE(args);
  396. }
  397. sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
  398. {
  399. int allocedEntitiyLen = 0;
  400. sp_cfg_start_args_t* args = MALLOC_T(sp_cfg_start_args_t);
  401. TOOLKIT_ASSERT(args);
  402. memset(args, 0, sizeof(sp_cfg_start_args_t));
  403. args->program = args->arguments = NULL;
  404. if (argc > 0) {
  405. args->program = CALLOC_T(strlen(argv[0]) + 1, char);
  406. if (!args->program) { exit(-1); }
  407. memset(args->program, '\0', sizeof(char) * (strlen(argv[0]) + 1));
  408. strcpy(args->program, argv[0]);
  409. printf("program: %s\n", args->program);
  410. std::string params;
  411. for (int i = 1, k=0; i < argc; ++i) {
  412. if(strcmp(argv[i], "--restart") == 0 || strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "-Rwait")/*QT*/ == 0 || strcmp(argv[i], "wait") == 0)
  413. continue;
  414. if (k != 0) params += " ";
  415. params += argv[i];
  416. k++;
  417. }
  418. if (!params.empty()) {
  419. args->arguments = CALLOC_T(params.length() + 1, char);
  420. if (!args->arguments) { exit(-1); }
  421. memset(args->arguments, '\0', sizeof(char) * (params.length()));
  422. strcpy(args->arguments, params.c_str());
  423. }
  424. printf("param: %s\n", args->arguments);
  425. }
  426. args->gui = 1;
  427. args->root = 1;
  428. static struct option spshell_options[] = {
  429. {"entity", required_argument, 0, 'E' },
  430. {"guardian", no_argument, 0, 'G'},
  431. {"test", no_argument, 0, 'T'},
  432. {"autotest", no_argument, 0, 'C'},
  433. {"debug", no_argument, 0, 'D'},
  434. {"ipc", required_argument, 0, 'I'},
  435. {"shutdown", no_argument, 0, 'S'},
  436. {"kill", no_argument, 0, 'K'},
  437. {"benchmark", no_argument, 0, 'B'},
  438. {"gui", required_argument, 0, 'U'},
  439. #ifdef WITH_DEBUG
  440. {"telnet", required_argument, 0, 'N' },
  441. #endif
  442. {"help", no_argument, 0, 'H'},
  443. {"version", no_argument, 0, 'V'},
  444. {"noroot", no_argument, 0, 'O'},
  445. {"restart", optional_argument, 0, 'R'},
  446. {"systemoff", optional_argument, 0, 'Y'},
  447. {"reboot", optional_argument, 0, 'J'},
  448. {"env", required_argument, 0, 'A' },
  449. {0, 0, 0, 0}
  450. };
  451. int spshell_index = 0;
  452. int c;
  453. while ((c = getopt_long(argc, argv, "E:GTCDI:SKBU:HVOR::Y::J::A:?", spshell_options, &spshell_index)) != EOF) {
  454. switch (c) {
  455. case 'C':
  456. #ifndef DEVOPS_ON_PRD
  457. //非生产情况下,才支持测试模式
  458. args->auto_test = 1;
  459. #endif // DEVOPS_ON_PRD
  460. break;
  461. case 'E':
  462. {
  463. if (optarg != NULL) {
  464. const int len = strlen(optarg);
  465. if (args->start_entities == NULL || len + strlen(args->start_entities) + 2 /*;\0*/ >= allocedEntitiyLen) {
  466. if (args->start_entities == NULL) {
  467. TOOLKIT_ASSERT(allocedEntitiyLen == 0);
  468. allocedEntitiyLen = 128;
  469. args->start_entities = CALLOC_T(allocedEntitiyLen, char);
  470. if (NULL == args->start_entities) {
  471. DestroyArgs(args);
  472. exit(-1);
  473. }
  474. } else {
  475. TOOLKIT_ASSERT(allocedEntitiyLen != 0);
  476. const int newLen = allocedEntitiyLen + len + 32;
  477. char* newAlloc = CALLOC_T(newLen, char);
  478. if (NULL == newAlloc) {
  479. DestroyArgs(args);
  480. exit(-1);
  481. }
  482. memset(newAlloc, '\0', sizeof(char) * newLen);
  483. strcpy_s(newAlloc, newLen, args->start_entities);
  484. FREE(args->start_entities);
  485. args->start_entities = newAlloc;
  486. allocedEntitiyLen = newLen;
  487. }
  488. }
  489. strcat(args->start_entities, optarg);
  490. strcat(args->start_entities, ";");
  491. }
  492. }
  493. break;
  494. case 'G':
  495. args->guardian_mode = 1;
  496. break;
  497. case 'D':
  498. args->debug_mode = 1;
  499. break;
  500. case 'T':
  501. args->test_mode = (args->test_mode | 1);
  502. break;
  503. case 'B':
  504. args->test_mode = (args->test_mode | 2);
  505. break;
  506. case 'I':
  507. if (optarg) {
  508. if (strnicmp(optarg, "tcp", strlen("tcp")) == 0)
  509. args->ipc_type = 1;
  510. }
  511. break;
  512. #ifdef WITH_DEBUG
  513. case 'N':
  514. if (optarg) {
  515. int nPort = 0;
  516. if (0 < sscanf(optarg, "%d", &nPort))
  517. args->telnet_port = nPort;
  518. }
  519. break;
  520. #endif
  521. case 'K':
  522. {
  523. osutil_terminate_related_process(relate_processes_ex, array_size(relate_processes_ex), 1);
  524. DestroyArgs(args);
  525. exit(0);
  526. }
  527. break;
  528. case 'U':
  529. if (optarg) {
  530. if (strnicmp(optarg, "ON", strlen("ON")) == 0)
  531. args->gui = 1;
  532. else if(strnicmp(optarg, "OFF", strlen("OFF")) == 0)
  533. args->gui = 0;
  534. }
  535. break;
  536. case 'A':
  537. if (optarg) {
  538. if (strnicmp(optarg, "ST", strlen("ST")) == 0)
  539. args->test_mode = (args->test_mode | 4);
  540. else if (strnicmp(optarg, "UAT", strlen("UAT")) == 0)
  541. args->test_mode = (args->test_mode | 8);
  542. }
  543. break;
  544. case 'V':
  545. {
  546. DestroyArgs(args);
  547. exit(0);
  548. break;
  549. }
  550. break;
  551. case 'O':
  552. args->root = 0;
  553. break;
  554. case 'R':
  555. g_restartMode = RESTART_MODE_NORMAL;
  556. if (optarg && strcmp(optarg, "wait") == 0) {
  557. g_restartMode = RESTART_MODE_PRE;
  558. }
  559. break;
  560. case 'S':
  561. g_restartMode = RESTART_MODE_SHUTDOWN;
  562. break;
  563. case 'Y':
  564. g_restartMode = RESTART_MODE_POWEROFF;
  565. if (optarg && strnicmp(optarg, "now", strlen("now")) == 0) {
  566. g_immediately = true;
  567. }
  568. break;
  569. case 'J':
  570. g_restartMode = RESTART_MODE_REBOOT;
  571. if (optarg && strnicmp(optarg, "now", strlen("now")) == 0) {
  572. g_immediately = true;
  573. }
  574. break;
  575. case 'H':
  576. case '?':
  577. default:
  578. DisplayUsage();
  579. DestroyArgs(args);
  580. exit(0);
  581. break;
  582. }
  583. }
  584. if (optind < argc) {
  585. while (optind < argc) {
  586. //DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("\t%s", argv[optind++]);
  587. }
  588. }
  589. if (args && args->start_entities != 0) {
  590. args->start_entities[strlen(args->start_entities) - 1] = '\0';
  591. }
  592. return args;
  593. }
  594. void normal_signal_handle(int num)
  595. {
  596. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("receive signal %d", num);
  597. signal(num, SIG_DFL);
  598. raise(num);
  599. }
  600. static bool NeedToRestartFramework()
  601. {
  602. //Shutdown 表明退掉框架不重启
  603. return !((g_restartMode == RESTART_MODE_SHUTDOWN
  604. || g_restartMode == RESTART_MODE_POWEROFF
  605. || g_restartMode == RESTART_MODE_REBOOT));
  606. }
  607. #if defined(_MSC_VER)
  608. ///*TODO(80374374@3/23/2023): osutil_detect_unique_app 替代 */
  609. static bool DetectDuplicateInstance(char** pNames, int nNum)
  610. {
  611. DWORD dwCurProcID = GetCurrentProcessId();
  612. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  613. std::shared_ptr<void> delHandleFun((void*)0, [&](void*) {
  614. if (NULL != hSnapshot)
  615. CloseHandle(hSnapshot);
  616. });
  617. if (hSnapshot) {
  618. PROCESSENTRY32 pe = {};
  619. pe.dwSize = sizeof(pe);
  620. if (Process32First(hSnapshot, &pe)) {
  621. do {
  622. for (int i = 0; i < nNum; i++) {
  623. if (stricmp(&pe.szExeFile[0], pNames[i]) == 0 && pe.th32ProcessID != dwCurProcID) {
  624. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
  625. if (hProc == NULL) {
  626. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("find duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  627. return false;
  628. }
  629. if (!SpTerminateProcess(hProc, pe.th32ProcessID)) {
  630. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate duplicated process %s fail, id: %d, error: %d",
  631. pNames[i], pe.th32ProcessID, GetLastError());
  632. return false;
  633. }
  634. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  635. }
  636. }
  637. } while (Process32Next(hSnapshot, &pe));
  638. }
  639. } else
  640. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("DetectDuplicateInstance can not enter Process32First!");
  641. return true;
  642. }
  643. #endif //_MSC_VER
  644. void SPBASE_API __stdcall setCurEntityIdx(int idx);
  645. std::string generateCenterSettingPath()
  646. {
  647. char pathbuf[1024] = "";
  648. int pathlen = ::GetModuleFileNameA(NULL, pathbuf, 1024);//获得GuiConsole路径
  649. // 替换掉单杠
  650. int times = 0;
  651. while (pathlen > 0) {
  652. if (pathbuf[pathlen--] == SPLIT_SLASH)
  653. times++;
  654. if (2 == times)
  655. break;
  656. }
  657. pathbuf[++pathlen] = '\0';
  658. std::string dstPath = pathbuf;
  659. dstPath.append(SPLIT_SLASH_STR "cfg" SPLIT_SLASH_STR "CenterSetting.ini");
  660. return dstPath;
  661. }
  662. int main(int argc, char** argv)
  663. {
  664. sp_cfg_start_args_t* args = DealWithArgs(argc, argv);
  665. #if defined(RVC_OS_LINUX)
  666. if (args->debug_mode) {
  667. SP::Perf::LeakDetector leakInstance;
  668. WLog_initRVC("SpShell");
  669. }
  670. #else
  671. //WLog_initRVC("SpShell");
  672. _CrtSetDebugFillThreshold(0);
  673. #endif //RVC_OS_LINUX
  674. #ifdef RVC_SAVEFILE
  675. bool saveFile = true;
  676. #else
  677. char tmp[MAX_LEN] = "";
  678. bool saveFile = false;
  679. if (Error_Succeed == sp_tryReadFromCenterSetting("Common", "SaveFile", tmp, MAX_LEN) && 0 == CSimpleStringA(tmp).Compare("1"))
  680. saveFile = true;
  681. #endif // RVC_SAVEFILE
  682. if (saveFile)
  683. sp_dbg_init("SpShell", 1);
  684. else
  685. sp_dbg_init("SpShell", 0);
  686. EntityResource::setSaveFile(saveFile);
  687. #if defined(RVC_OS_LINUX)
  688. sp_dbg_set_level(XLOG_LEVEL_DEBUG);
  689. #endif //RVC_OS_LINUX
  690. if (argc > 1) {
  691. std::string args_str;
  692. char cmdline[1024] = { '\0' };
  693. for (int i = 0; i < argc; ++i) {
  694. sprintf_s(cmdline, 1024, "%s", argv[i]);
  695. if (i != 0) args_str += " ";
  696. args_str += cmdline;
  697. }
  698. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("prefix: %s", args_str.c_str());
  699. }
  700. #if defined(_MSC_VER)
  701. auto centersettingPath = generateCenterSettingPath();
  702. load_debugLevelInCentersetting(centersettingPath.c_str());
  703. load_specialRunInfoInCentersetting(centersettingPath.c_str());
  704. auto setAffinity = [](long ulCpuMask) {
  705. HANDLE hCurrentProc;
  706. DWORD_PTR dwpProcAffinityMask = ulCpuMask;
  707. // Obtain a usable handle of the current process
  708. hCurrentProc = GetCurrentProcess();
  709. // Get the old affinity mask
  710. SetProcessAffinityMask(hCurrentProc, dwpProcAffinityMask);
  711. SetProcessAffinityUpdateMode(hCurrentProc, PROCESS_AFFINITY_ENABLE_AUTO_UPDATE);
  712. CloseHandle(hCurrentProc);
  713. };
  714. setAffinity(1);
  715. char* arrProcName[] = { "SpShell.exe", "SpHost.exe", "SpHost_re.exe" };
  716. //实际可以加快这个过程,如果进程过多会比较慢
  717. //后续可考虑用mutex进行控制
  718. if (!DetectDuplicateInstance(&arrProcName[0], sizeof(arrProcName) / sizeof(arrProcName[0]))) {
  719. DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_REPEATPROCESS)("检测到重复spshell/sphost进程,系统启动失败!!!");
  720. Sleep(10000);
  721. return -200;
  722. }
  723. #else
  724. if (!!g_restartMode) {
  725. /** 因为没有明显的提示,等的时间(次数)不宜过长 [Gifur@202475]*/
  726. /*
  727. 阶段一:框架收到退出事件后会调用实体的stop接口,具体实现在app.cpp::stop_all_stated_entity
  728. 阶段二:框架会温和杀死实体相关进程
  729. 阶段三:框架会强制杀死实体相关进程
  730. */
  731. const DWORD eachPreTimeout = 500;//等待进程自行退出的每次等待间隔时间
  732. const int maxPreTimies = 6;//等待进程自行退出的最大等待次数
  733. const DWORD eachTimeout = 2000;//杀死进程后的每次等待间隔时间
  734. const int maxTimes = 15;//杀死进程后的最大等待次数
  735. const int gentleKillThresholdTimes = 10; //允许温和杀死实体进程的次数
  736. const DWORD skipInterval = 5;
  737. int currTimes = 0, preTimes = 0;
  738. bool needWait = (g_restartMode > RESTART_MODE_NORMAL && !g_immediately); //Rwait 框架触发的重启
  739. const bool needlessRestart = !NeedToRestartFramework();
  740. int aliveCount = 0, lastAliveCount(1000);
  741. char** relates = relate_processes;
  742. int reletes_cnt = relate_processes_count;
  743. if (needWait) {
  744. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("等待应用进程退出...");
  745. }
  746. if (needlessRestart) {
  747. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("to shutdown guardian...");
  748. char* tmp_processes[] = { guardian_execute_name };
  749. osutil_terminate_related_process(tmp_processes, array_size(tmp_processes), 1);
  750. relates = relate_processes_ex;
  751. reletes_cnt = relate_processes_ex_count;
  752. }
  753. bool switch_flag = false;
  754. while (switch_flag || !osutil_detect_unique_app(relates, reletes_cnt, &aliveCount, NULL)) {
  755. if (!needWait && currTimes++ >= maxTimes) {
  756. DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM)("detect ex-spshell or sphost process, abort cur boot !!!");
  757. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("等待应用进程退出超时,请尝试重启机器!");
  758. sp_dbg_term();
  759. DestroyArgs(args);
  760. return -200;
  761. } else {
  762. if (needWait) {
  763. Sleep(eachPreTimeout);
  764. if (preTimes++ >= maxPreTimies && (aliveCount >= lastAliveCount)) {
  765. needWait = false;
  766. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("set need wait flag false");
  767. }
  768. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("wait... last active process count:%d, curr process count: %d, ppid: %d", lastAliveCount, aliveCount, GetParentProcessID());
  769. lastAliveCount = aliveCount;
  770. } else {
  771. const int force_flag = gentleKillThresholdTimes < currTimes ? 1 : 0;
  772. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("detect ex-spshell or sphost process %d, %d, %d terminate all !!!", preTimes, currTimes, force_flag);
  773. osutil_terminate_related_process(relates, reletes_cnt, force_flag);
  774. Sleep(eachTimeout);
  775. }
  776. const DWORD consumedTime = (currTimes * eachTimeout) / 1000 + (eachPreTimeout * preTimes) / 1000;
  777. if (consumedTime > 0) {
  778. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("等待应用进程退出,已等待 %d 秒...", consumedTime);
  779. }
  780. }
  781. //aliveCount = 0; //important!!!
  782. switch_flag = (((preTimes + currTimes) % skipInterval) != 0);
  783. if (!switch_flag) {
  784. aliveCount = 0;
  785. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("will enter osutil_detect_unique_app");
  786. }
  787. }
  788. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("finish detecting unique app.");
  789. if (needlessRestart) {
  790. const DWORD sleepMillsecs = 2000;
  791. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("restart mode: %d", g_restartMode);
  792. if (g_restartMode == RESTART_MODE_SHUTDOWN) {
  793. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,退出当前窗口...");
  794. } else if (g_restartMode == RESTART_MODE_POWEROFF) {
  795. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,准备关机...");
  796. osutil_shutdown_system();
  797. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,正在关机...");
  798. } else if (g_restartMode == RESTART_MODE_REBOOT) {
  799. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,准备关机重启...");
  800. osutil_restart_system();
  801. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,正在关机并重启...");
  802. }
  803. Sleep(sleepMillsecs);
  804. sp_dbg_term();
  805. DestroyArgs(args);
  806. return 0;
  807. }
  808. } else if (!osutil_detect_unique_app(relate_processes, array_size(relate_processes), NULL, NULL)) {
  809. do {
  810. bool clearTotal = false;
  811. int innerClearEnhance = 0;
  812. do
  813. {
  814. osutil_terminate_related_process(relate_processes, array_size(relate_processes), innerClearEnhance > 8 ? 1 : 0);
  815. Sleep(3000);
  816. int count = MAX_ALIVE_PROCESS_COUNT;
  817. alive_process_info processes[MAX_ALIVE_PROCESS_COUNT];
  818. memset(processes, 0, sizeof(processes));
  819. if (osutil_detect_unique_app(relate_processes, array_size(relate_processes), &count, processes)) {
  820. clearTotal = true;
  821. break;
  822. }
  823. } while (innerClearEnhance++ < 10);
  824. if (clearTotal) {
  825. break;
  826. }
  827. DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("clear ex-spshell/sphost process failed!");
  828. sp_dbg_term();
  829. DestroyArgs(args);
  830. return -200;
  831. } while (false);
  832. }
  833. #endif //_MSC_VER
  834. sp_runtask_loadLogLevel();
  835. sp_tryquickStartCef();
  836. create_log_producer_default("SpShell", 0);
  837. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("===================SpShell start=====================");
  838. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("process id: %d, saveFile:%d", GetCurrentProcessId(), saveFile);
  839. if (argc > 1) {
  840. std::string args_str;
  841. char cmdline[1024] = { '\0' };
  842. for (int i = 0; i < argc; ++i) {
  843. sprintf_s(cmdline, 1024, "%s", argv[i]);
  844. if (i != 0) args_str += " ";
  845. args_str += cmdline;
  846. }
  847. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)(args_str.c_str());
  848. SP_TRACE(args_str.c_str());
  849. }
  850. if (!IsProcessRunAsAdmin()) {
  851. if (args->root) {
  852. DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM)("current process need run with administrator or root privilege !!!");
  853. DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_NOPRIVILEGE)("需要以管理员权限运行!!!");
  854. Sleep(10000);
  855. sp_dbg_term();
  856. DestroyArgs(args);
  857. return -201;
  858. } else {
  859. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("current process requires normal privilege.");
  860. }
  861. } else {
  862. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("current process has been run with administrator or root privilege.");
  863. args->root = (char)1;
  864. #if defined(_MSC_VER)
  865. SYSTEM_INFO SystemInfo;
  866. GetSystemInfo(&SystemInfo);
  867. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("当前以管理员权限运行, curProcessId:%d, curVersion:%s ,dwNumberOfProcessors=%u, dwActiveProcessorMask=%u, wProcessorLevel=%u, wProcessorArchitecture=%u, dwPageSize=%u",
  868. GetCurrentProcessId(), STRFILEVER, SystemInfo.dwNumberOfProcessors, SystemInfo.dwActiveProcessorMask, SystemInfo.wProcessorLevel,
  869. SystemInfo.wProcessorArchitecture, SystemInfo.dwPageSize);
  870. #endif //_MSC_VER
  871. }
  872. #ifdef RVC_OS_WIN
  873. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Config firewall policies......");
  874. // 设置防火墙注册表配置
  875. AddFirewallRulesEx();
  876. setlocale(LC_ALL, "chs");
  877. #else
  878. if (NULL == setlocale(LC_ALL, "zh_CN.UTF-8")) {
  879. //zh_CN.UTF-8 zh_CN.GBK
  880. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("setlocale failed: %s", strerror(errno));
  881. }
  882. #endif //RVC_OS_WIN
  883. ResetEnvPath();
  884. #ifdef RVC_OS_WIN
  885. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Config working set......");
  886. SetWorkingSet();//获取设置内存使用率,4G
  887. #endif //RVC_OS_WIN
  888. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("basic config success");
  889. #ifdef RVC_OS_WIN
  890. // 检测是否Win8及64位
  891. OSVERSIONINFO ver = {};
  892. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  893. GetVersionEx(&ver);
  894. bool bWin8 = (ver.dwMajorVersion >= 7 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2)); //version over 7 or over 6.2
  895. SYSTEM_INFO sysInfo = {};
  896. GetNativeSystemInfo(&sysInfo);
  897. bool bX64 = (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
  898. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("OS version: %s %d.%d.%d , SetErrorMode %s", bX64 ? "windows 64" : "windows 32", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
  899. 0 == SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX) ? "success" : "failed");
  900. SetUnhandledExceptionFilter(&SuppressError);
  901. #endif //RVC_OS_WIN
  902. auto msg_lamda_func = [&](const char* msg, bool ctritial)->void {
  903. };
  904. //////////////////////////////////////////////////////////////////////////
  905. #if defined(_MSC_VER)
  906. auto rc = app_init(args);
  907. int result = rc.first;
  908. #else
  909. int result = app_init(args, msg_lamda_func);
  910. #endif //_MSC_VER
  911. //////////////////////////////////////////////////////////////////////////
  912. if (result == 0)
  913. {
  914. sp_trace_term();
  915. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("run circle loop in main thread!!");
  916. result = app_run();
  917. app_term();
  918. }
  919. else
  920. {
  921. uint32_t waitIntervals = 10000;
  922. if (sp_trace_exist()) {
  923. char* last_err = NULL;
  924. sp_trace_retrieve(&last_err, NULL);
  925. if (last_err) {
  926. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to show last error dialog...");
  927. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("应用启动失败:%s", last_err);
  928. waitIntervals = 1;
  929. FREE(last_err);
  930. DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to show last error dialog done!");
  931. }
  932. sp_trace_term();
  933. }
  934. #if defined(_MSC_VER)
  935. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
  936. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_APPINITERR)(rc.second.GetData());
  937. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("!!!!!! 启动失败,请检查dbg\\spshell日志排除故障 !!!!!!");
  938. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
  939. #else
  940. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
  941. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_APPINITERR)("!!!!!! Startup failed, get more detail information from dbg/spshell !!!!!!");
  942. DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
  943. #endif //_MSC_VER
  944. app_upload_last_log();
  945. Sleep(waitIntervals);
  946. }
  947. #ifdef RVC_OS_WIN
  948. if (bWin8 && !bX64) {
  949. EnableCharmbar();
  950. }
  951. #endif //RVC_OS_WIN
  952. sp_dbg_term();
  953. DestroyArgs(args);
  954. return result;
  955. }
  956. #ifdef RVC_OS_WIN
  957. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  958. {
  959. return main(__argc, __argv);
  960. }
  961. #endif //RVC_OS_WIN