1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030 |
- #include "precompile.h"
- #include "app.h"
- #include "osutil.h"
- #include "version.h"
- #include "memtrace.h"
- #include "sp_def.h"
- #ifdef RVC_OS_WIN
- #include <DbgHelp.h>
- #include <TlHelp32.h>
- #include <shellapi.h>
- #else
- #include <unistd.h>
- #endif //RVC_OS_WIN
- #include "fileutil.h"
- #include "iniutil.h"
- #include "getopt.h"
- #include "toolkit.h"
- #include "SimpleString.h"
- #include "md5file.h"
- #include "SpBase.h"
- #include "SpComm.hpp"
- #ifdef RVC_OS_WIN
- #include <io.h>
- #include "sp_firewallControl.h"
- #else
- #include <unistd.h>
- #include <sys/syscall.h>
- #endif //RVC_OS_WIN
- #include <map>
- #include <iterator>
- #include <fstream>
- #include "libtoolkit/log.h"
- #include <signal.h>
- #include "SpBase.h"
- #include "sp_dbg_export.h"
- #include "versionBase.h"
- #include "base64File.hpp"
- #include "RVCEventCode.h"
- #include "dbgutil.h"
- #include <locale.h>
- #include <winpr/library.h>
- #include <winpr/environment.h>
- #include <winpr/registry.h>
- #include <winpr/sysinfo.h>
- #ifdef realloc
- #undef realloc //(p, s)
- #endif
- using namespace std;
- #include <spbase/sp_runTask.h>
- #ifndef RVC_OS_WIN
- static int GetParentProcessID()
- {
- #if 0
- return getppid();
- #else
- return (int)syscall(SYS_getppid);
- #endif
- }
- #endif //NOT _WIN32
- #ifdef RVC_OS_WIN
- static char spshell_execute_name[] = "SpShell.exe";
- static char sphost_execute_name[] = "SpHost.exe";
- static char guardian_execute_name[] = "Guardian.exe";
- static char cefclient_execute_name[] = "cefclient.exe";
- #else
- static char spshell_execute_name[] = "spshell";
- static char sphost_execute_name[] = "sphost";
- static char guardian_execute_name[] = "guardian";
- static char cefclient_execute_name[] = "cefclient";
- #endif //_WIN32
- #define RESTART_MODE_DEFAULT 0
- #define RESTART_MODE_NORMAL 1
- #define RESTART_MODE_PRE 2
- #define RESTART_MODE_SHUTDOWN 3
- #define RESTART_MODE_POWEROFF 4
- #define RESTART_MODE_REBOOT 5
- #define DRIVER_NAME "HelloDDK"
- #define DRIVER_PATH "InterceptDll.sys"
- #define SET_EVENT \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define GET_SHARE_ADD \
- CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
- HANDLE g_hEvent = NULL;
- bool g_bMD5Exist = false;
- bool g_bWow64 = false;
- CSimpleStringA g_strMD5ListPath;
- static int g_restartMode = RESTART_MODE_DEFAULT;
- static bool g_immediately = false;
- char* relate_processes[] = { spshell_execute_name, sphost_execute_name, cefclient_execute_name };
- const int relate_processes_count = 3;
- char* relate_processes_ex[] = { spshell_execute_name, sphost_execute_name, guardian_execute_name, cefclient_execute_name };
- const int relate_processes_ex_count = 4;
- const int MAX_LEN = 256;
- //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
- static bool IsSpPathType(const CSimpleStringA& value, const char* key)
- {
- const int leastLength = strlen("Run//1.0.0.0/") + strlen(key);
- CSimpleStringA path(value.GetData());
- if (path.IsNullOrEmpty() || path.GetLength() < leastLength) return false;
- for (int i = 0; i < path.GetLength(); ++i) {
- if (path[i] >= 'A' && path[i] <= 'Z') path[i] = path[i] + ('a' - 'A');
- }
- const int sionPos = path.IndexOf(key);
- const int verPos = sionPos + strlen(key) + strlen(SPLIT_SLASH_STR);
- if (sionPos < 0) return false;
- int suffixPos = -1, i;
- int dotCnt = 0;
- bool lastIsNum = false;
- for (i = verPos; i < path.GetLength() && (path[i] >= '0' && path[i] <= '9' || path[i] == '.'); ++i) {
- lastIsNum = !(path[i] == '.');
- if (!lastIsNum) dotCnt++;
- }
- //if (i == path.GetLength() && dotCnt == 3 && lastIsNum) return true; //D:\Run\version\3.7.1.0
- if (i >= path.GetLength() || dotCnt != 3 || !lastIsNum)
- return false;
- return true;
- }
- static CSimpleStringA CutSpPathFromPathValue(const char* value, const char* prefix)
- {
- CSimpleStringA path(value);
- CSimpleStringA result(true);
- CAutoArray<CSimpleStringA> values = path.Split(ENV_SEP_CHAR);
- if (values.GetCount() <= 0) {
- return path;
- }
- for (int i = 0; i < values.GetCount(); ++i) {
- if (!values[i].IsStartWith(prefix) && !IsSpPathType(values[i], "version") &&! IsSpPathType(values[i], "dep")) {
- if (!result.IsNullOrEmpty()) result += ENV_SEP_STR;
- result += values[i];
- }
- }
- //if (!result.IsNullOrEmpty() && path[path.GetLength() - 1] == ENV_SEP_CHAR) {
- // result += ENV_SEP_STR;
- //}
- return result;
- }
- static void ResetEnvPath()
- {
- char path[MAX_PATH];
- char *buf;
- DWORD size;
- #if defined(_MSC_VER)
- const char* name = "PATH";
- #else
- const char* name = "LD_LIBRARY_PATH";
- #endif //_MSC_VER
- // set current path
- GetModuleFileNameA(NULL, path, MAX_PATH);
- *strrchr(path, SPLIT_SLASH) = 0; //bin
- *strrchr(path, SPLIT_SLASH) = 0; //1.2.3.4
- SetCurrentDirectoryA(path);
- size = GetEnvironmentVariableA(name, NULL, 0);
- buf = (char*)malloc(size+MAX_PATH*3);
- size = GetEnvironmentVariableA(name, buf, size);
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("origin path:%s", buf);
- CSimpleStringA newValue = CutSpPathFromPathValue(buf, path);
- memset(buf, 0, size + MAX_PATH * 3);
- size = newValue.GetLength();
- if (!newValue.IsNullOrEmpty()) {
- strcpy(buf, newValue.GetData());
- strcat(buf, ENV_SEP_STR);
- }
- // append bin sub dir to %PATH%
- strcat(path, SPLIT_SLASH_STR "bin");
- strcat(buf, path);
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("new path:%s", buf);
- SetEnvironmentVariableA(name, buf);
- free(buf);
- SetEnvironmentVariableA("ModuleName", "SpShell");
- }
- #ifdef RVC_OS_WIN
- static void SetWorkingSet()
- {
- SIZE_T dwMinSize, dwMaxSize;
- HANDLE hCurrProcess = GetCurrentProcess();
- GetProcessWorkingSetSize(hCurrProcess, &dwMinSize, &dwMaxSize);
- if (dwMaxSize < (2 << 20))
- dwMaxSize = 2 << 20;
- SetProcessWorkingSetSize(hCurrProcess, dwMinSize, dwMaxSize);
- }
- static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo)
- {
- static bool hasCall = false;
- if (hasCall)
- ExitProcess(Error_Exception);
- else
- hasCall = true;
- char tmp[MAX_PATH];
- HANDLE hDumpFile;
- std::string dmpFileStr;
- GetModuleFileNameA(NULL, tmp, MAX_PATH);
- *strrchr(tmp, SPLIT_SLASH) = 0;
- *strrchr(tmp, SPLIT_SLASH) = 0;
- *strrchr(tmp, SPLIT_SLASH) = 0;
- *strrchr(tmp, SPLIT_SLASH) = 0;
- *strrchr(tmp, SPLIT_SLASH) = 0;
- wsprintfA(tmp, "%s\\rvc\\dmp\\expt.spshell.%d.%s.dmp", tmp, GetCurrentProcessId(), STRFILEVER);
- hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE,
- 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
- if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) )
- {
- MINIDUMP_EXCEPTION_INFORMATION mdei;
- MINIDUMP_TYPE mdt;
- mdei.ThreadId = GetCurrentThreadId();
- mdei.ExceptionPointers = ExceptionInfo;
- mdei.ClientPointers = FALSE;
- mdt = MiniDumpNormal;
- MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
- hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 );
- CloseHandle( hDumpFile );
- }
- char szCmd[256];
- sprintf_s(szCmd, 256, "TASKKILL /f /im sphost.exe");
- system(szCmd);
- sprintf_s(szCmd, 256, "TASKKILL /f /im sphost_re.exe");
- system(szCmd);
- 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"
- , tmp, dmpFileStr.length() ,dmpFileStr.c_str());
- ExitProcess(Error_Exception); // exit process to suppress reporting exception
- return EXCEPTION_EXECUTE_HANDLER;
- }
- __declspec(dllimport) bool DisableCharmbar();
- __declspec(dllimport) bool EnableCharmbar();
- static void AutoHideTaskBar(bool bHide)
- {
- APPBARDATA apBar;
- memset(&apBar, 0, sizeof(apBar));
- apBar.cbSize = sizeof(apBar);
- apBar.lParam = bHide ? ABS_AUTOHIDE : ABS_ALWAYSONTOP;
- apBar.hWnd = FindWindow("Shell_TrayWnd", NULL);
- if (apBar.hWnd != NULL)
- {
- SHAppBarMessage(ABM_SETSTATE, &apBar);
- }
- }
- static bool AddFirewallRules()
- {
- char szBinDir[MAX_PATH] = {};
- GetModuleFileNameA(NULL, szBinDir, MAX_PATH);
- *strrchr(szBinDir, SPLIT_SLASH) = 0;
- int nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpHost_re\"\"", NULL, SW_HIDE);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpHost\"\"", NULL, SW_HIDE);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpGuardian\"\"", NULL, SW_HIDE);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"cefclient\"\"", NULL, SW_HIDE);
- char szParam[1024] = {};
- sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpShell\"\" dir=out program=\"\"%s\\spshell.exe\"\" action=allow\"", szBinDir);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
- sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpHost\"\" dir=out program=\"\"%s\\sphost.exe\"\" action=allow\"", szBinDir);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
- sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpGuardian\"\" dir=out program=\"\"%s\\guardian.exe\"\" action=allow\"", szBinDir);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
- sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"cefclient\"\" dir=out program=\"\"%s\\Chromium\\cefclient.exe\"\" action=allow\"", szBinDir);
- nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
- return nRet > 32;
- }
- int AddFireAddFirewallRulesThread(void* param)
- {
- LOG_FUNCTION();
- if (!sp_CheckAllRules())
- {
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("设置Windows防火墙策略失败!!!");
- Sleep(10000);
- return -1;
- }
- else
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("设置Windows防火墙策略成功!!!");
- return 0;
- }
- static void AddFirewallRulesEx()
- {
- CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)& AddFireAddFirewallRulesThread, NULL, 0, NULL));
- }
- #endif //RVC_OS_WIN
- /*!
- * at Linux, judge whether current process runs as root privilege.
- * @return : True only if run as admin or root
- */
- static bool IsProcessRunAsAdmin()
- {
- BOOL bAdmin = FALSE;
- #ifdef RVC_OS_WIN
- SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
- PSID AdministratorsGroup = NULL;
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start AllocateAndInitializeSid");
- if (AllocateAndInitializeSid(
- &NtAuthority,
- 2,
- SECURITY_BUILTIN_DOMAIN_RID,
- DOMAIN_ALIAS_RID_ADMINS,
- 0, 0, 0, 0, 0, 0,
- &AdministratorsGroup))
- {
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start CheckTokenMembership");
- CheckTokenMembership(NULL, AdministratorsGroup, &bAdmin);
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("start FreeSid");
- FreeSid(AdministratorsGroup);
- }
- #else
- if (geteuid() == 0) {
- bAdmin = TRUE;
- } else {
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("current process is not run as root privilege, euid:%u, uid:%d", geteuid(), getuid());
- }
- #endif //RVC_OS_WIN
- return bAdmin == TRUE;
- }
- static bool SpTerminateProcess(HANDLE hProc, DWORD dwProcID)
- {
- if (!TerminateProcess(hProc, -1))
- {
- #ifdef RVC_OS_WIN
- char szCmd[256];
- int nRet = 0;
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate process %d fail: 0x%X, retry with taskkill", dwProcID, GetLastError());
- sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", dwProcID);
- WinExec(szCmd, SW_HIDE);
- return nRet != -1;
- #else
- return false;
- #endif //RVC_OS_WIN
- }
- return true;
- }
- void DisplayUsage()
- {
- char szHelp[4097] = { '\0' };
- sprintf_s(szHelp, 4096, "\n"
- "Usage spshell [--entity {EntityName}][--guardian][--test][--benchmark][--kill][--debug][--ipc <pipe|tcp>][--restart][--noroot]\n"
- "--entity {EntityName} --启动特定的实体,选项后面输入实体名称\n"
- "--guardian --以后台进程的方式运行,暂未实现\n"
- "--test --以测试模式运行\n"
- "--autotest --自动化验证\n"
- "--debug --以调试模式运行,输出更为详细的日志\n"
- "--benchmark --以压力测试的模式启动\n"
- "--kill --直接杀死终端相关进程,比如 spshell, sphost 等\n"
- "--shutdown --彻底退出终端相关进程,不单独使用\n"
- "--systemoff --执行系统关机指令,关机前会彻底退出应用,不单独使用\n"
- "--reboot --执行系统重启指令,重启关机前会彻底退出应用,不单独使用\n"
- "--ipc <pipe|tcp> --指定实体间的通讯方式,使用管道或TCP,默认使用管道\n"
- "--noroot -- 允许以非管理员或Root权限方式启动\n"
- "--restart --重启当前应用\n"
- "--version --显示当前的版本\n"
- #ifdef WITH_DEBUG
- "--telnet {listern port} --激活远程调用功能\n"
- #endif
- );
- #ifdef RVC_OS_WIN
- MessageBoxA(NULL, szHelp, "Spshell Usage Tip", MB_OK);
- #else
- printf("%s\n", szHelp);
- #endif
- }
- static void DestroyArgs(sp_cfg_start_args_t* args)
- {
- if (args != NULL) {
- FREE(args->program);
- FREE(args->arguments);
- }
- FREE(args);
- }
- sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
- {
- int allocedEntitiyLen = 0;
- sp_cfg_start_args_t* args = MALLOC_T(sp_cfg_start_args_t);
- TOOLKIT_ASSERT(args);
- memset(args, 0, sizeof(sp_cfg_start_args_t));
- args->program = args->arguments = NULL;
- if (argc > 0) {
- args->program = CALLOC_T(strlen(argv[0]) + 1, char);
- if (!args->program) { exit(-1); }
- memset(args->program, '\0', sizeof(char) * (strlen(argv[0]) + 1));
- strcpy(args->program, argv[0]);
- printf("program: %s\n", args->program);
- std::string params;
- for (int i = 1, k=0; i < argc; ++i) {
- if(strcmp(argv[i], "--restart") == 0 || strcmp(argv[i], "-R") == 0 || strcmp(argv[i], "-Rwait")/*QT*/ == 0 || strcmp(argv[i], "wait") == 0)
- continue;
- if (k != 0) params += " ";
- params += argv[i];
- k++;
- }
- if (!params.empty()) {
- args->arguments = CALLOC_T(params.length() + 1, char);
- if (!args->arguments) { exit(-1); }
- memset(args->arguments, '\0', sizeof(char) * (params.length()));
- strcpy(args->arguments, params.c_str());
- }
- printf("param: %s\n", args->arguments);
- }
- args->gui = 1;
- args->root = 1;
- static struct option spshell_options[] = {
- {"entity", required_argument, 0, 'E' },
- {"guardian", no_argument, 0, 'G'},
- {"test", no_argument, 0, 'T'},
- {"autotest", no_argument, 0, 'C'},
- {"debug", no_argument, 0, 'D'},
- {"ipc", required_argument, 0, 'I'},
- {"shutdown", no_argument, 0, 'S'},
- {"kill", no_argument, 0, 'K'},
- {"benchmark", no_argument, 0, 'B'},
- {"gui", required_argument, 0, 'U'},
- #ifdef WITH_DEBUG
- {"telnet", required_argument, 0, 'N' },
- #endif
- {"help", no_argument, 0, 'H'},
- {"version", no_argument, 0, 'V'},
- {"noroot", no_argument, 0, 'O'},
- {"restart", optional_argument, 0, 'R'},
- {"systemoff", optional_argument, 0, 'Y'},
- {"reboot", optional_argument, 0, 'J'},
- {"env", required_argument, 0, 'A' },
- {0, 0, 0, 0}
- };
- int spshell_index = 0;
- int c;
- while ((c = getopt_long(argc, argv, "E:GTCDI:SKBU:HVOR::Y::J::A:?", spshell_options, &spshell_index)) != EOF) {
- switch (c) {
- case 'C':
- #ifndef DEVOPS_ON_PRD
- //非生产情况下,才支持测试模式
- args->auto_test = 1;
- #endif // DEVOPS_ON_PRD
- break;
- case 'E':
- {
- if (optarg != NULL) {
- const int len = strlen(optarg);
- if (args->start_entities == NULL || len + strlen(args->start_entities) + 2 /*;\0*/ >= allocedEntitiyLen) {
- if (args->start_entities == NULL) {
- TOOLKIT_ASSERT(allocedEntitiyLen == 0);
- allocedEntitiyLen = 128;
- args->start_entities = CALLOC_T(allocedEntitiyLen, char);
- if (NULL == args->start_entities) {
- DestroyArgs(args);
- exit(-1);
- }
- } else {
- TOOLKIT_ASSERT(allocedEntitiyLen != 0);
- const int newLen = allocedEntitiyLen + len + 32;
- char* newAlloc = CALLOC_T(newLen, char);
- if (NULL == newAlloc) {
- DestroyArgs(args);
- exit(-1);
- }
- memset(newAlloc, '\0', sizeof(char) * newLen);
- strcpy_s(newAlloc, newLen, args->start_entities);
- FREE(args->start_entities);
- args->start_entities = newAlloc;
- allocedEntitiyLen = newLen;
- }
- }
- strcat(args->start_entities, optarg);
- strcat(args->start_entities, ";");
- }
- }
- break;
- case 'G':
- args->guardian_mode = 1;
- break;
- case 'D':
- args->debug_mode = 1;
- break;
- case 'T':
- args->test_mode = (args->test_mode | 1);
- break;
- case 'B':
- args->test_mode = (args->test_mode | 2);
- break;
- case 'I':
- if (optarg) {
- if (strnicmp(optarg, "tcp", strlen("tcp")) == 0)
- args->ipc_type = 1;
- }
- break;
- #ifdef WITH_DEBUG
- case 'N':
- if (optarg) {
- int nPort = 0;
- if (0 < sscanf(optarg, "%d", &nPort))
- args->telnet_port = nPort;
- }
- break;
- #endif
- case 'K':
- {
- osutil_terminate_related_process(relate_processes_ex, array_size(relate_processes_ex), 1);
- DestroyArgs(args);
- exit(0);
- }
- break;
- case 'U':
- if (optarg) {
- if (strnicmp(optarg, "ON", strlen("ON")) == 0)
- args->gui = 1;
- else if(strnicmp(optarg, "OFF", strlen("OFF")) == 0)
- args->gui = 0;
- }
- break;
- case 'A':
- if (optarg) {
- if (strnicmp(optarg, "ST", strlen("ST")) == 0)
- args->test_mode = (args->test_mode | 4);
- else if (strnicmp(optarg, "UAT", strlen("UAT")) == 0)
- args->test_mode = (args->test_mode | 8);
- }
- break;
- case 'V':
- {
- DestroyArgs(args);
- exit(0);
- break;
- }
- break;
- case 'O':
- args->root = 0;
- break;
- case 'R':
- g_restartMode = RESTART_MODE_NORMAL;
- if (optarg && strcmp(optarg, "wait") == 0) {
- g_restartMode = RESTART_MODE_PRE;
- }
- break;
- case 'S':
- g_restartMode = RESTART_MODE_SHUTDOWN;
- break;
- case 'Y':
- g_restartMode = RESTART_MODE_POWEROFF;
- if (optarg && strnicmp(optarg, "now", strlen("now")) == 0) {
- g_immediately = true;
- }
- break;
- case 'J':
- g_restartMode = RESTART_MODE_REBOOT;
- if (optarg && strnicmp(optarg, "now", strlen("now")) == 0) {
- g_immediately = true;
- }
- break;
- case 'H':
- case '?':
- default:
- DisplayUsage();
- DestroyArgs(args);
- exit(0);
- break;
- }
- }
- if (optind < argc) {
- while (optind < argc) {
- //DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("\t%s", argv[optind++]);
- }
- }
- if (args && args->start_entities != 0) {
- args->start_entities[strlen(args->start_entities) - 1] = '\0';
- }
- return args;
- }
- void normal_signal_handle(int num)
- {
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("receive signal %d", num);
- signal(num, SIG_DFL);
- raise(num);
- }
- static bool NeedToRestartFramework()
- {
- //Shutdown 表明退掉框架不重启
- return !((g_restartMode == RESTART_MODE_SHUTDOWN
- || g_restartMode == RESTART_MODE_POWEROFF
- || g_restartMode == RESTART_MODE_REBOOT));
- }
- #if defined(_MSC_VER)
- ///*TODO(80374374@3/23/2023): osutil_detect_unique_app 替代 */
- static bool DetectDuplicateInstance(char** pNames, int nNum)
- {
- DWORD dwCurProcID = GetCurrentProcessId();
- HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- std::shared_ptr<void> delHandleFun((void*)0, [&](void*) {
- if (NULL != hSnapshot)
- CloseHandle(hSnapshot);
- });
- if (hSnapshot) {
- PROCESSENTRY32 pe = {};
- pe.dwSize = sizeof(pe);
- if (Process32First(hSnapshot, &pe)) {
- do {
- for (int i = 0; i < nNum; i++) {
- if (stricmp(&pe.szExeFile[0], pNames[i]) == 0 && pe.th32ProcessID != dwCurProcID) {
- HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
- if (hProc == NULL) {
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("find duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
- return false;
- }
- if (!SpTerminateProcess(hProc, pe.th32ProcessID)) {
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate duplicated process %s fail, id: %d, error: %d",
- pNames[i], pe.th32ProcessID, GetLastError());
- return false;
- }
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("terminate duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
- }
- }
- } while (Process32Next(hSnapshot, &pe));
- }
- } else
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("DetectDuplicateInstance can not enter Process32First!");
- return true;
- }
- #endif //_MSC_VER
- void SPBASE_API __stdcall setCurEntityIdx(int idx);
- std::string generateCenterSettingPath()
- {
- char pathbuf[1024] = "";
- int pathlen = ::GetModuleFileNameA(NULL, pathbuf, 1024);//获得GuiConsole路径
- // 替换掉单杠
- int times = 0;
- while (pathlen > 0) {
- if (pathbuf[pathlen--] == SPLIT_SLASH)
- times++;
- if (2 == times)
- break;
- }
- pathbuf[++pathlen] = '\0';
- std::string dstPath = pathbuf;
- dstPath.append(SPLIT_SLASH_STR "cfg" SPLIT_SLASH_STR "CenterSetting.ini");
- return dstPath;
- }
- int main(int argc, char** argv)
- {
- //SendTestLog_loki("spshell", "log", "startup");
- sp_cfg_start_args_t* args = DealWithArgs(argc, argv);
- #if defined(RVC_OS_LINUX)
- if (args->debug_mode) {
- SP::Perf::LeakDetector leakInstance;
- WLog_initRVC("SpShell");
- }
- #else
- //WLog_initRVC("SpShell");
- _CrtSetDebugFillThreshold(0);
- #endif //RVC_OS_LINUX
- #ifdef RVC_SAVEFILE
- bool saveFile = true;
- #else
- char tmp[MAX_LEN] = "";
- bool saveFile = false;
- if (Error_Succeed == sp_tryReadFromCenterSetting("Common", "SaveFile", tmp, MAX_LEN) && 0 == CSimpleStringA(tmp).Compare("1"))
- saveFile = true;
- #endif // RVC_SAVEFILE
- if (saveFile)
- sp_dbg_init("SpShell", 1);
- else
- sp_dbg_init("SpShell", 0);
- EntityResource::setSaveFile(saveFile);
- #if defined(RVC_OS_LINUX)
- sp_dbg_set_level(XLOG_LEVEL_DEBUG);
- #endif //RVC_OS_LINUX
- if (argc > 1) {
- std::string args_str;
- char cmdline[1024] = { '\0' };
- for (int i = 0; i < argc; ++i) {
- sprintf_s(cmdline, 1024, "%s", argv[i]);
- if (i != 0) args_str += " ";
- args_str += cmdline;
- }
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("prefix: %s", args_str.c_str());
- }
- #if defined(_MSC_VER)
- //TODO: CrossPlaform 等良瑜确认,应该不再涉及本地集中配置了 [Gifur@2025820]
- auto centersettingPath = generateCenterSettingPath();
- load_debugLevelInCentersetting(centersettingPath.c_str());
- load_specialRunInfoInCentersetting(centersettingPath.c_str());
- auto setAffinity = [](long ulCpuMask) {
- HANDLE hCurrentProc;
- DWORD_PTR dwpProcAffinityMask = ulCpuMask;
- // Obtain a usable handle of the current process
- hCurrentProc = GetCurrentProcess();
- // Get the old affinity mask
- SetProcessAffinityMask(hCurrentProc, dwpProcAffinityMask);
- SetProcessAffinityUpdateMode(hCurrentProc, PROCESS_AFFINITY_ENABLE_AUTO_UPDATE);
- CloseHandle(hCurrentProc);
- };
- setAffinity(1);
- char* arrProcName[] = { "SpShell.exe", "SpHost.exe", "SpHost_re.exe" };
- //实际可以加快这个过程,如果进程过多会比较慢
- //后续可考虑用mutex进行控制
- if (!DetectDuplicateInstance(&arrProcName[0], sizeof(arrProcName) / sizeof(arrProcName[0]))) {
- DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_REPEATPROCESS)("检测到重复spshell/sphost进程,系统启动失败!!!");
- Sleep(10000);
- return -200;
- }
- #else
- if (!!g_restartMode) {
- /** 因为没有明显的提示,等的时间(次数)不宜过长 [Gifur@202475]*/
- /*
- 阶段一:框架收到退出事件后会调用实体的stop接口,具体实现在app.cpp::stop_all_stated_entity
- 阶段二:框架会温和杀死实体相关进程
- 阶段三:框架会强制杀死实体相关进程
- */
- const DWORD eachPreTimeout = 500;//等待进程自行退出的每次等待间隔时间
- const int maxPreTimies = 6;//等待进程自行退出的最大等待次数
- const DWORD eachTimeout = 2000;//杀死进程后的每次等待间隔时间
- const int maxTimes = 15;//杀死进程后的最大等待次数
- const int gentleKillThresholdTimes = 10; //允许温和杀死实体进程的次数
- const DWORD skipInterval = 5;
- int currTimes = 0, preTimes = 0;
- bool needWait = (g_restartMode > RESTART_MODE_NORMAL && !g_immediately); //Rwait 框架触发的重启
- const bool needlessRestart = !NeedToRestartFramework();
- int aliveCount = 0, lastAliveCount(1000);
- char** relates = relate_processes;
- int reletes_cnt = relate_processes_count;
- if (needWait) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("等待应用进程退出...");
- }
- if (needlessRestart) {
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("to shutdown guardian...");
- char* tmp_processes[] = { guardian_execute_name };
- osutil_terminate_related_process(tmp_processes, array_size(tmp_processes), 1);
- relates = relate_processes_ex;
- reletes_cnt = relate_processes_ex_count;
- }
- bool switch_flag = false;
- while (switch_flag || !osutil_detect_unique_app(relates, reletes_cnt, &aliveCount, NULL)) {
- if (!needWait && currTimes++ >= maxTimes) {
- DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM)("detect ex-spshell or sphost process, abort cur boot !!!");
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("等待应用进程退出超时,请尝试重启机器!");
- sp_dbg_term();
- DestroyArgs(args);
- return -200;
- } else {
- if (needWait) {
- Sleep(eachPreTimeout);
- if (preTimes++ >= maxPreTimies && (aliveCount >= lastAliveCount)) {
- needWait = false;
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("set need wait flag false");
- }
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("wait... last active process count:%d, curr process count: %d, ppid: %d", lastAliveCount, aliveCount, GetParentProcessID());
- lastAliveCount = aliveCount;
- } else {
- const int force_flag = gentleKillThresholdTimes < currTimes ? 1 : 0;
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("detect ex-spshell or sphost process %d, %d, %d terminate all !!!", preTimes, currTimes, force_flag);
- osutil_terminate_related_process(relates, reletes_cnt, force_flag);
- Sleep(eachTimeout);
- }
- const DWORD consumedTime = (currTimes * eachTimeout) / 1000 + (eachPreTimeout * preTimes) / 1000;
- if (consumedTime > 0) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("等待应用进程退出,已等待 %d 秒...", consumedTime);
- }
- }
- //aliveCount = 0; //important!!!
- switch_flag = (((preTimes + currTimes) % skipInterval) != 0);
- if (!switch_flag) {
- aliveCount = 0;
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("will enter osutil_detect_unique_app");
- }
- }
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("finish detecting unique app.");
- if (needlessRestart) {
- const DWORD sleepMillsecs = 2000;
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("restart mode: %d", g_restartMode);
- if (g_restartMode == RESTART_MODE_SHUTDOWN) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,退出当前窗口...");
- } else if (g_restartMode == RESTART_MODE_POWEROFF) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,准备关机...");
- osutil_shutdown_system();
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,正在关机...");
- } else if (g_restartMode == RESTART_MODE_REBOOT) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,准备关机重启...");
- osutil_restart_system();
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("应用进程已完全清理,正在关机并重启...");
- }
- Sleep(sleepMillsecs);
- sp_dbg_term();
- DestroyArgs(args);
- return 0;
- }
- } else if (!osutil_detect_unique_app(relate_processes, array_size(relate_processes), NULL, NULL)) {
- do {
- bool clearTotal = false;
- int innerClearEnhance = 0;
- do
- {
- osutil_terminate_related_process(relate_processes, array_size(relate_processes), innerClearEnhance > 8 ? 1 : 0);
- Sleep(3000);
- int count = MAX_ALIVE_PROCESS_COUNT;
- alive_process_info processes[MAX_ALIVE_PROCESS_COUNT];
- memset(processes, 0, sizeof(processes));
- if (osutil_detect_unique_app(relate_processes, array_size(relate_processes), &count, processes)) {
- clearTotal = true;
- break;
- }
- } while (innerClearEnhance++ < 10);
- if (clearTotal) {
- break;
- }
- DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("clear ex-spshell/sphost process failed!");
- sp_dbg_term();
- DestroyArgs(args);
- return -200;
- } while (false);
- }
- #endif //_MSC_VER
- sp_runtask_loadLogLevel();
- sp_tryquickStartCef();
- create_log_producer_default("SpShell", 0);
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("===================SpShell start=====================");
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("process id: %d, saveFile:%d", GetCurrentProcessId(), saveFile);
- if (argc > 1) {
- std::string args_str;
- char cmdline[1024] = { '\0' };
- for (int i = 0; i < argc; ++i) {
- sprintf_s(cmdline, 1024, "%s", argv[i]);
- if (i != 0) args_str += " ";
- args_str += cmdline;
- }
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)(args_str.c_str());
- SP_TRACE(args_str.c_str());
- }
- if (!IsProcessRunAsAdmin()) {
- if (args->root) {
- DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM)("current process need run with administrator or root privilege !!!");
- DbgWithLink(LOG_LEVEL_FATAL, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_NOPRIVILEGE)("需要以管理员权限运行!!!");
- Sleep(10000);
- sp_dbg_term();
- DestroyArgs(args);
- return -201;
- } else {
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("current process requires normal privilege.");
- }
- } else {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("current process has been run with administrator or root privilege.");
- args->root = (char)1;
- #if defined(_MSC_VER)
- SYSTEM_INFO SystemInfo;
- GetSystemInfo(&SystemInfo);
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("当前以管理员权限运行, curProcessId:%d, curVersion:%s ,dwNumberOfProcessors=%u, dwActiveProcessorMask=%u, wProcessorLevel=%u, wProcessorArchitecture=%u, dwPageSize=%u",
- GetCurrentProcessId(), STRFILEVER, SystemInfo.dwNumberOfProcessors, SystemInfo.dwActiveProcessorMask, SystemInfo.wProcessorLevel,
- SystemInfo.wProcessorArchitecture, SystemInfo.dwPageSize);
- #endif //_MSC_VER
- }
- #ifdef RVC_OS_WIN
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Config firewall policies......");
- // 设置防火墙注册表配置
- AddFirewallRulesEx();
- setlocale(LC_ALL, "chs");
- #else
- if (NULL == setlocale(LC_ALL, "zh_CN.UTF-8")) {
- //zh_CN.UTF-8 zh_CN.GBK
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("setlocale failed: %s", strerror(errno));
- }
- #endif //RVC_OS_WIN
- ResetEnvPath();
- #ifdef RVC_OS_WIN
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Config working set......");
- SetWorkingSet();//获取设置内存使用率,4G
- #endif //RVC_OS_WIN
- DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("basic config success");
- #ifdef RVC_OS_WIN
- // 检测是否Win8及64位
- OSVERSIONINFO ver = {};
- ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&ver);
- bool bWin8 = (ver.dwMajorVersion >= 7 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2)); //version over 7 or over 6.2
- SYSTEM_INFO sysInfo = {};
- GetNativeSystemInfo(&sysInfo);
- bool bX64 = (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
- 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,
- 0 == SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX) ? "success" : "failed");
- SetUnhandledExceptionFilter(&SuppressError);
- #endif //RVC_OS_WIN
- auto msg_lamda_func = [&](const char* msg, bool ctritial)->void {
- };
- //////////////////////////////////////////////////////////////////////////
- #if defined(_MSC_VER)
- auto rc = app_init(args);
- int result = rc.first;
- #else
- int result = app_init(args, msg_lamda_func);
- #endif //_MSC_VER
- //////////////////////////////////////////////////////////////////////////
- if (result == 0)
- {
- sp_trace_term();
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("run circle loop in main thread!!");
- result = app_run();
- app_term();
- }
- else
- {
- uint32_t waitIntervals = 10000;
- if (sp_trace_exist()) {
- char* last_err = NULL;
- sp_trace_retrieve(&last_err, NULL);
- if (last_err) {
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to show last error dialog...");
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("应用启动失败:%s", last_err);
- waitIntervals = 1;
- FREE(last_err);
- DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to show last error dialog done!");
- }
- sp_trace_term();
- }
- #if defined(_MSC_VER)
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_APPINITERR)(rc.second.GetData());
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("!!!!!! 启动失败,请检查dbg\\spshell日志排除故障 !!!!!!");
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
- #else
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).setResultMsg(RTAERR_SPSHELL_APPINITERR)("!!!!!! Startup failed, get more detail information from dbg/spshell !!!!!!");
- DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("======================================================");
- #endif //_MSC_VER
- app_upload_last_log();
- Sleep(waitIntervals);
- }
- #ifdef RVC_OS_WIN
- if (bWin8 && !bX64) {
- EnableCharmbar();
- }
- #endif //RVC_OS_WIN
- sp_dbg_term();
- DestroyArgs(args);
- return result;
- }
- #ifdef RVC_OS_WIN
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
- {
- return main(__argc, __argv);
- }
- #endif //RVC_OS_WIN
|