spshell.cpp 39 KB

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