spshell.cpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. #include "precompile.h"
  2. #include "app.h"
  3. #include "osutil.h"
  4. #include "sp_dbg_export.h"
  5. #ifdef _WIN32
  6. #include <DbgHelp.h>
  7. #include <TlHelp32.h>
  8. #include <shellapi.h>
  9. #else
  10. #include <unistd.h>
  11. #endif //_WIN32
  12. #include "fileutil.h"
  13. #include "iniutil.h"
  14. #include "getopt.h"
  15. #include "toolkit.h"
  16. #include "SimpleString.h"
  17. #include "SpBase.h"
  18. #include "SpComm.hpp"
  19. #ifdef _WIN32
  20. #include <io.h>
  21. #endif //_WIN32
  22. #include <locale.h>
  23. #include <winpr/library.h>
  24. #include <winpr/environment.h>
  25. #include <winpr/registry.h>
  26. #include <winpr/sysinfo.h>
  27. using namespace std;
  28. #define DRIVER_NAME "HelloDDK"
  29. #define DRIVER_PATH "InterceptDll.sys"
  30. #define SET_EVENT \
  31. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
  32. #define GET_SHARE_ADD \
  33. CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
  34. HANDLE g_hEvent = NULL;
  35. bool g_bMD5Exist = false;
  36. bool g_bWow64 = false;
  37. CSimpleStringA g_strMD5ListPath;
  38. static void SetEnvPath()
  39. {
  40. char path[MAX_PATH];
  41. char *buf;
  42. DWORD size;
  43. const char *var = "PATH";
  44. // set current path
  45. GetModuleFileNameA(NULL, path, MAX_PATH);
  46. *strrchr(path, SPLIT_SLASH) = 0;
  47. *strrchr(path, SPLIT_SLASH) = 0;
  48. SetCurrentDirectoryA(path);
  49. // append dep sub dir to %PATH%
  50. strcat(path, SPLIT_SLASH_STR "dep");
  51. size = GetEnvironmentVariableA(var, NULL, 0);
  52. buf = (char*)malloc(size+MAX_PATH*3);
  53. size = GetEnvironmentVariableA(var, buf, size);
  54. strcpy(buf+size, ENV_SEP_STR);
  55. strcat(buf+size, path);
  56. *strrchr(path, SPLIT_SLASH) = 0;
  57. strcat(path, SPLIT_SLASH_STR "bin");
  58. strcat(buf+size, ENV_SEP_STR);
  59. strcat(buf+size, path);
  60. *strrchr(path, SPLIT_SLASH) = 0;
  61. strcat(path, SPLIT_SLASH_STR "dev");
  62. strcat(buf+size, ENV_SEP_STR);
  63. strcat(buf+size, path);
  64. *strrchr(path, SPLIT_SLASH) = 0;
  65. strcat(path, SPLIT_SLASH_STR "imdep");
  66. strcat(buf + size, ENV_SEP_STR);
  67. strcat(buf + size, path);
  68. SetEnvironmentVariableA(var, buf);
  69. free(buf);
  70. SetEnvironmentVariableA("ModuleName", "SpShell");
  71. }
  72. #ifdef _WIN32
  73. // 获取设置内存使用率,4G
  74. static void SetWorkingSet()
  75. {
  76. SIZE_T dwMinSize, dwMaxSize;
  77. HANDLE hCurrProcess = GetCurrentProcess();
  78. GetProcessWorkingSetSize(hCurrProcess, &dwMinSize, &dwMaxSize);
  79. if (dwMaxSize < (2 << 20))
  80. dwMaxSize = 2 << 20;
  81. SetProcessWorkingSetSize(hCurrProcess, dwMinSize, dwMaxSize);
  82. }
  83. static LONG WINAPI SuppressError(struct _EXCEPTION_POINTERS* ExceptionInfo)
  84. {
  85. char tmp[MAX_PATH];
  86. HANDLE hDumpFile;
  87. wsprintfA(tmp, ".\\expt.spshell.%d.%d.dmp", GetCurrentThreadId(), GetCurrentProcessId());
  88. hDumpFile = CreateFileA( tmp, GENERIC_READ | GENERIC_WRITE,
  89. 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  90. if( ( hDumpFile != NULL ) && ( hDumpFile != INVALID_HANDLE_VALUE ) )
  91. {
  92. MINIDUMP_EXCEPTION_INFORMATION mdei;
  93. MINIDUMP_TYPE mdt;
  94. mdei.ThreadId = GetCurrentThreadId();
  95. mdei.ExceptionPointers = ExceptionInfo;
  96. mdei.ClientPointers = FALSE;
  97. mdt = MiniDumpNormal;
  98. MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
  99. hDumpFile, mdt, (ExceptionInfo != 0) ? &mdei : 0, 0, 0 );
  100. CloseHandle( hDumpFile );
  101. }
  102. char szCmd[256];
  103. sprintf_s(szCmd, 256, "TASKKILL /f /im sphost.exe");
  104. system(szCmd);
  105. ExitProcess(Error_Exception); // exit process to suppress reporting exception
  106. return EXCEPTION_EXECUTE_HANDLER;
  107. }
  108. static void DisableSetUnhandledExceptionFilter()
  109. {
  110. void* addr = (void*)GetProcAddress(LoadLibrary("kernel32.dll"), "SetUnhandledExceptionFilter");
  111. if (addr) {
  112. DWORD dwOldFlag, dwTempFlag;
  113. unsigned char code[] = {0x33, 0xC0, 0xC2, 0x04, 0x00}; // xor eax,eax; ret 4;
  114. //VirtualProtect(addr, sizeof(code), PAGE_READWRITE, &dwOldFlag);
  115. VirtualProtectEx(GetCurrentProcess(), addr, sizeof(code), PAGE_EXECUTE_READWRITE, &dwOldFlag);
  116. WriteProcessMemory(GetCurrentProcess(), addr, code, sizeof(code), NULL);
  117. VirtualProtect(addr, sizeof(code), dwOldFlag, &dwTempFlag);
  118. }
  119. }
  120. __declspec(dllimport) bool DisableCharmbar();
  121. __declspec(dllimport) bool EnableCharmbar();
  122. static HANDLE create_process(const char *app)
  123. {
  124. //BOOL bRet;
  125. STARTUPINFOA si = { sizeof(STARTUPINFOA) };
  126. si.wShowWindow = SW_SHOWMAXIMIZED;
  127. si.dwFlags = STARTF_USESHOWWINDOW;
  128. PROCESS_INFORMATION pi;
  129. DWORD dwSessionId;
  130. HANDLE hUserTokenDup, hThisToken;
  131. HANDLE hProcess = NULL;
  132. dwSessionId = WTSGetActiveConsoleSessionId();
  133. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hThisToken)) {
  134. LUID luid;
  135. TOKEN_PRIVILEGES tp;
  136. LPVOID pEnv = NULL;
  137. LookupPrivilegeValueA(NULL, SE_DEBUG_NAME, &luid);
  138. tp.PrivilegeCount = 1;
  139. tp.Privileges[0].Luid = luid;
  140. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  141. DuplicateTokenEx(hThisToken, MAXIMUM_ALLOWED, NULL,
  142. SecurityIdentification, TokenPrimary, &hUserTokenDup);
  143. SetTokenInformation(hUserTokenDup,
  144. TokenSessionId, (void*)&dwSessionId, sizeof(DWORD));
  145. AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
  146. (PTOKEN_PRIVILEGES)NULL, NULL);
  147. //CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE);
  148. if (CreateProcessAsUserA(hUserTokenDup, NULL,
  149. (LPSTR)app,
  150. NULL, NULL, FALSE, 0, pEnv, NULL, &si, &pi))
  151. {
  152. CloseHandle(pi.hThread);
  153. hProcess = pi.hProcess;
  154. }
  155. else
  156. sp_dbg_warn("create process failed! Error : ", GetLastError());
  157. //if (pEnv)
  158. //DestroyEnvironmentBlock(pEnv);
  159. CloseHandle(hUserTokenDup);
  160. CloseHandle(hThisToken);
  161. }
  162. else {
  163. sp_dbg_warn("open process token failed! Error : ", GetLastError());
  164. }
  165. return hProcess;
  166. }
  167. static void AutoHideTaskBar(bool bHide)
  168. {
  169. APPBARDATA apBar;
  170. memset(&apBar, 0, sizeof(apBar));
  171. apBar.cbSize = sizeof(apBar);
  172. apBar.lParam = bHide ? ABS_AUTOHIDE : ABS_ALWAYSONTOP;
  173. apBar.hWnd = FindWindow("Shell_TrayWnd", NULL);
  174. if (apBar.hWnd != NULL)
  175. {
  176. SHAppBarMessage(ABM_SETSTATE, &apBar);
  177. }
  178. }
  179. static bool AddRegIntValue(HKEY hKey, const char *szSubKey, const char *szKeyName, DWORD dwValue, bool bWin64)
  180. {
  181. HKEY hSubKey;
  182. LONG nRet = ::RegCreateKeyEx(hKey,
  183. szSubKey,
  184. 0,
  185. NULL,
  186. 0,
  187. bWin64 ? (KEY_ALL_ACCESS | KEY_WOW64_64KEY) : (KEY_ALL_ACCESS | KEY_WOW64_32KEY),
  188. NULL,
  189. &hSubKey,
  190. NULL);
  191. if (nRet != ERROR_SUCCESS)
  192. return false;
  193. nRet = RegSetValueExA(hSubKey, szKeyName, 0, REG_DWORD, (BYTE*)&dwValue, sizeof(DWORD));
  194. RegCloseKey(hSubKey);
  195. return (nRet == ERROR_SUCCESS);
  196. }
  197. static bool AddFirewallRules()
  198. {
  199. char szBinDir[MAX_PATH] = {};
  200. GetModuleFileNameA(NULL, szBinDir, MAX_PATH);
  201. *strrchr(szBinDir, SPLIT_SLASH) = 0;
  202. int nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  203. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpShell\"\"", NULL, SW_HIDE);
  204. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpHost\"\"", NULL, SW_HIDE);
  205. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", "/s /c \"netsh advfirewall firewall delete rule name=\"\"SpGuardian\"\"", NULL, SW_HIDE);
  206. char szParam[1024] = {};
  207. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpShell\"\" dir=out program=\"\"%s\\spshell.exe\"\" action=allow\"", szBinDir);
  208. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  209. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpHost\"\" dir=out program=\"\"%s\\sphost.exe\"\" action=allow\"", szBinDir);
  210. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  211. sprintf_s(szParam, 1024, "/s /c \"netsh advfirewall firewall add rule name=\"\"SpGuardian\"\" dir=out program=\"\"%s\\guardian.exe\"\" action=allow\"", szBinDir);
  212. nRet = (int)ShellExecute(NULL, "open", "cmd.exe", szParam, NULL, SW_HIDE);
  213. return nRet > 32;
  214. }
  215. int AddFireAddFirewallRulesThread(void* param)
  216. {
  217. if (!AddFirewallRules())
  218. {
  219. sp_dbg_fatal("设置Windows防火墙策略失败!!!");
  220. Sleep(10000);
  221. return -1;
  222. }
  223. else
  224. sp_dbg_info("设置Windows防火墙策略成功!!!");
  225. return 0;
  226. }
  227. static void AddFirewallRulesEx()
  228. {
  229. CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)& AddFireAddFirewallRulesThread, NULL, 0, NULL));
  230. }
  231. static bool DisableWindowsCharmBar(bool bX64)
  232. {
  233. if (!bX64)
  234. {
  235. if (DisableCharmbar())
  236. {
  237. sp_dbg_info("disable windows 8 charmbar succ");
  238. return true;
  239. }
  240. else
  241. {
  242. sp_dbg_error("disable windows 8 charmbar fail: %x", GetLastError());
  243. return false;
  244. }
  245. }
  246. else
  247. {
  248. // 由于64位Windows Hook需要64位进程和64位dll,需要独立启动MetroWatcher64注入
  249. char path[MAX_PATH] = {};
  250. GetModuleFileNameA(NULL, path, MAX_PATH);
  251. *strrchr(path, SPLIT_SLASH) = 0;
  252. char app[MAX_PATH] = {};
  253. sprintf(app, "%s\\MetroWatcher64.exe %d", path, GetCurrentProcessId());
  254. if (create_process(app) != NULL)
  255. {
  256. sp_dbg_info("disable windows 8 (64bit) charmbar succ");
  257. return true;
  258. }
  259. else
  260. {
  261. sp_dbg_error("disable windows 8 (64bit) charmbar fail: %x", GetLastError());
  262. return false;
  263. }
  264. }
  265. }
  266. #endif //_WIN32
  267. /*!
  268. * at Linux, judge whether current process runs as root privilege.
  269. * @return : True only if run as admin or root
  270. */
  271. static bool IsProcessRunAsAdmin()
  272. {
  273. BOOL bAdmin = FALSE;
  274. #ifdef _WIN32
  275. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  276. PSID AdministratorsGroup = NULL;
  277. sp_dbg_info("start AllocateAndInitializeSid");
  278. if (AllocateAndInitializeSid(
  279. &NtAuthority,
  280. 2,
  281. SECURITY_BUILTIN_DOMAIN_RID,
  282. DOMAIN_ALIAS_RID_ADMINS,
  283. 0, 0, 0, 0, 0, 0,
  284. &AdministratorsGroup)) {
  285. sp_dbg_info("start CheckTokenMembership");
  286. CheckTokenMembership(NULL, AdministratorsGroup, &bAdmin);
  287. sp_dbg_info("start FreeSid");
  288. FreeSid(AdministratorsGroup);
  289. }
  290. #else
  291. if (geteuid() == 0) {
  292. bAdmin = TRUE;
  293. } else {
  294. sp_dbg_warn("current process is not run as root privilege, euid:%u, uid:%d", geteuid(), getuid());
  295. }
  296. #endif //_WIN32
  297. return bAdmin == TRUE;
  298. }
  299. const char *GetMachineType()
  300. {
  301. auto env = sp_get_env();
  302. if (env == NULL)
  303. {
  304. sp_dbg_error("sp_get_env return null");
  305. return NULL;
  306. }
  307. return env->cfg->root_ini->machine_type;
  308. }
  309. const char *GetCenterSettingNameBySite(const char *pszSite)
  310. {
  311. if ((stricmp(pszSite, "CMB.LIB") == 0) // 行内大堂
  312. || (stricmp(pszSite, "CMB.SSB") == 0))//
  313. {
  314. return "CenterSetting.LAN.ini";
  315. }
  316. else if ((stricmp(pszSite, "CMB.LSS") == 0) //
  317. || (stricmp(pszSite, "CMB.FLB") == 0) //
  318. || (stricmp(pszSite, "CMB.OSB") == 0) //
  319. || (stricmp(pszSite, "CMB.SMM") == 0)) //
  320. {
  321. return "CenterSetting.DMZ.ini";
  322. }
  323. else
  324. {
  325. return "CenterSetting.DMZ.ini";
  326. }
  327. }
  328. const char *GetWebSiteFromConfig()
  329. {
  330. auto env = sp_get_env();
  331. if (env == NULL)
  332. {
  333. sp_dbg_error("sp_get_env return null");
  334. return NULL;
  335. }
  336. auto pszCenterSettingName = GetCenterSettingNameBySite(env->cfg->root_ini->site);
  337. char szCfgFile[256] = {};
  338. sprintf_s(szCfgFile, sizeof(szCfgFile), "%s\\%s", env->dir->cfg_path, pszCenterSettingName);
  339. // 判断对应集中配置文件是否存在,不存在则重命名CenterSetting.ini
  340. if (!ExistsFileA(szCfgFile))
  341. {
  342. char szBackupCfgFile[256] = {};
  343. sprintf_s(szBackupCfgFile, sizeof(szCfgFile), "%s\\CenterSetting.ini", env->dir->cfg_path);
  344. // default CenterSetting config file has been removed ? I can see it in depository [3/19/2020 7:47 Gifur]
  345. if (ExistsFileA(szBackupCfgFile))
  346. {
  347. rename(szBackupCfgFile, szCfgFile);
  348. }
  349. }
  350. // get machine type
  351. auto pMachineType = env->cfg->root_ini->machine_type;
  352. char szKeyName[256] = {};
  353. sprintf(szKeyName, "IEBrowser.%s.URL", pMachineType);
  354. auto pWebSite = inifile_read_str(szCfgFile, "HealthManager", szKeyName, NULL);
  355. if (pWebSite == NULL || strlen(pWebSite)==0)
  356. {
  357. if (pWebSite) FREE(pWebSite);
  358. sp_dbg_error("read %s from %s return null", szKeyName, pszCenterSettingName);
  359. return NULL;
  360. }
  361. // http://99.1.100.217/RVC.Web/default.aspx http://99.1.100.217/RVC.Web/default2.aspx
  362. // get root url
  363. auto p = strchr(pWebSite + 7, '/');
  364. if (p != NULL)
  365. *p = 0;
  366. p = strchr(pWebSite + 7, ':');
  367. if (p == NULL)
  368. strcat(pWebSite, ":80");
  369. return pWebSite;
  370. }
  371. #ifdef _WIN32
  372. static bool WebcamMicrophoneAuthorize(bool bWin64)
  373. {
  374. const char *pWetSite = GetWebSiteFromConfig();
  375. if(pWetSite == NULL)
  376. {
  377. sp_dbg_error("GetWebSiteFromConfig failed!");
  378. return false;
  379. }
  380. TCHAR szSubKey[1024] = { 0 };
  381. sprintf(szSubKey, "Software\\AppDataLow\\Software\\Microsoft\\Silverlight\\Permissions\\%s", pWetSite);
  382. free((void*)(char*)pWetSite);
  383. if (!AddRegIntValue(HKEY_CURRENT_USER, szSubKey, "WebcamAndMicrophone", 0x00000011, bWin64))
  384. {
  385. sp_dbg_error("创建SL摄像机麦克风权限注册表项失败!");
  386. return false;
  387. }
  388. sp_dbg_info("add silverlight webcam and microphone permission succeed");
  389. return true;
  390. }
  391. #endif //_WIN32
  392. static bool SpTerminateProcess(HANDLE hProc, DWORD dwProcID)
  393. {
  394. if (!TerminateProcess(hProc, -1))
  395. {
  396. #ifdef _WIN32
  397. char szCmd[256];
  398. int nRet = 0;
  399. sp_dbg_debug("terminate process %d fail: 0x%X, retry with taskkill", dwProcID, GetLastError());
  400. sprintf_s(szCmd, 256, "TASKKILL /PID %d /F", dwProcID);
  401. WinExec(szCmd, SW_HIDE);
  402. return nRet != -1;
  403. #else
  404. return false;
  405. #endif //_WIN32
  406. }
  407. return true;
  408. }
  409. // replace it with osutil from libtoolkit [3/18/2020 19:01 Gifur]
  410. /*
  411. static bool DetectDuplicateInstance(char **pNames, int nNum)
  412. {
  413. sp_dbg_info("start GetCurrentProcessId");
  414. DWORD dwCurProcID = GetCurrentProcessId();
  415. sp_dbg_info("start CreateToolhelp32Snapshot");
  416. HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  417. if (hSnapshot)
  418. {
  419. PROCESSENTRY32 pe = {};
  420. pe.dwSize = sizeof(pe);
  421. sp_dbg_info("start Process32First");
  422. if (Process32First(hSnapshot, &pe))
  423. {
  424. do
  425. {
  426. for (int i = 0; i < nNum; i++)
  427. {
  428. if (stricmp(&pe.szExeFile[0], pNames[i]) == 0 && pe.th32ProcessID != dwCurProcID)
  429. {
  430. sp_dbg_info("start OpenProcess");
  431. HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
  432. if (hProc == NULL)
  433. {
  434. sp_dbg_error("find duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  435. CloseHandle(hSnapshot);
  436. return false;
  437. }
  438. if (!SpTerminateProcess(hProc, pe.th32ProcessID))
  439. {
  440. sp_dbg_error("terminate duplicated process %s fail, id: %d, error: %d", pNames[i], pe.th32ProcessID, GetLastError());
  441. CloseHandle(hSnapshot);
  442. return false;
  443. }
  444. sp_dbg_info("terminate duplicated process: %s, id: %d", pNames[i], pe.th32ProcessID);
  445. }
  446. }
  447. } while (Process32Next(hSnapshot, &pe));
  448. }
  449. CloseHandle(hSnapshot);
  450. }
  451. return true;
  452. }
  453. */
  454. #ifdef _WIN32
  455. static bool LoadInterceptDllDriver(char* lpszDriverName,char* lpszDriverPath)
  456. {
  457. /************************ 加载DLL监控驱动的代码*******************************
  458. ① 调用OpenSCManager,打开SCM管理器.如果返回NULL,则返回失败,否则继续
  459. ② 调用CreateService,创建服务,创建成功则转步骤 ⑥
  460. ③ 用GetLastError的得到错误返回值
  461. ④ 返回值为ERROR_IO_PENDING,说明服务已经创建过,用OpenService打开此服务.
  462. ⑤ 返回值为其他值, 创建武服务失败,返回失败.
  463. ⑥ 调用StartService开启服务
  464. ⑦ 成功返回
  465. ************************************************************************/
  466. CSimpleStringA strDriverPath;
  467. TCHAR szPath[MAX_PATH] = {0};
  468. GetModuleFileNameA(NULL, szPath, MAX_PATH);
  469. *strrchr(szPath, SPLIT_SLASH) = 0;
  470. strDriverPath = szPath;
  471. if (g_bWow64)
  472. {
  473. strDriverPath += SPLIT_SLASH_STR "InterceptDll_64.sys";
  474. }
  475. else
  476. {
  477. strDriverPath += SPLIT_SLASH_STR "InterceptDll_32.sys";
  478. }
  479. sp_dbg_info("strDriverPath[%s]",strDriverPath);
  480. bool bRet = false;
  481. SC_HANDLE hServiceMgr=NULL;
  482. SC_HANDLE hServiceDDK=NULL;
  483. hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  484. if(hServiceMgr == NULL)
  485. {
  486. sp_dbg_fatal("OpenSCManager() Failed %d!", GetLastError());
  487. bRet = false;
  488. goto BeforeLeave;
  489. }
  490. else
  491. {
  492. sp_dbg_info("OpenSCManager() ok");
  493. }
  494. hServiceDDK = CreateService(hServiceMgr,
  495. lpszDriverName, // 驱动程序的在注册表中的名字
  496. lpszDriverName, // 注册表驱动程序的 DisplayName 值
  497. SERVICE_ALL_ACCESS, // 加载驱动程序的访问权限
  498. SERVICE_KERNEL_DRIVER, // 表示加载的服务是驱动程序
  499. SERVICE_DEMAND_START, // 注册表驱动程序的 Start 值
  500. SERVICE_ERROR_IGNORE, // 注册表驱动程序的 ErrorControl 值
  501. //szDriverImagePath, // 注册表驱动程序的 ImagePath 值
  502. strDriverPath.GetData(),
  503. //"C:\\Run\\version\\1.10.0.0\\bin\\InterceptDll.sys",
  504. NULL,
  505. NULL,
  506. NULL,
  507. NULL,
  508. NULL);
  509. DWORD dwRtn;
  510. if(hServiceDDK == NULL) // 判断服务是否失败
  511. {
  512. dwRtn = GetLastError();
  513. if(dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)
  514. {
  515. sp_dbg_fatal("CreateService() Faild %d !", dwRtn);
  516. bRet = false;
  517. goto BeforeLeave;
  518. }
  519. else
  520. {
  521. sp_dbg_info("CreateService() Faild Service is ERROR_IO_PENDING or ERROR_SERVICE_EXISTS!");
  522. }
  523. // 驱动程序已经加载,只需要打开
  524. hServiceDDK = OpenService(hServiceMgr, lpszDriverName, SERVICE_ALL_ACCESS);
  525. if(hServiceDDK == NULL)
  526. {
  527. // 如果打开服务也失败,则意味错误
  528. dwRtn = GetLastError();
  529. sp_dbg_fatal("OpenService() Faild %d!", dwRtn);
  530. bRet = false;
  531. goto BeforeLeave;
  532. }
  533. else
  534. {
  535. sp_dbg_info("OpenService() ok!");
  536. }
  537. }
  538. else
  539. {
  540. sp_dbg_info("CrateService() ok !");
  541. }
  542. bRet= StartService(hServiceDDK, NULL, NULL);
  543. if(!bRet)
  544. {
  545. DWORD dwRtn = GetLastError();
  546. if(dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING)
  547. {
  548. sp_dbg_fatal("StartService() Faild %d !", dwRtn);
  549. bRet = false;
  550. goto BeforeLeave;
  551. }
  552. else
  553. {
  554. if(dwRtn == ERROR_IO_PENDING)
  555. {
  556. // 设备被挂住
  557. sp_dbg_fatal("StartService() Faild ERROR_IO_PENDING!");
  558. bRet = false;
  559. goto BeforeLeave;
  560. }
  561. else
  562. {
  563. // 服务已经开启
  564. sp_dbg_fatal("StartService() Faild ERROR_SERVICE_ALREADY_RUNNING!");
  565. bRet = true;
  566. goto BeforeLeave;
  567. }
  568. }
  569. }
  570. else
  571. {
  572. sp_dbg_info("StartService() ok!");
  573. }
  574. bRet = true;
  575. BeforeLeave:
  576. if(hServiceDDK)
  577. {
  578. CloseServiceHandle(hServiceDDK); // 服务句柄
  579. }
  580. if(hServiceMgr)
  581. {
  582. CloseServiceHandle(hServiceMgr); // SCM句柄
  583. }
  584. return bRet;
  585. }
  586. static bool UnloadInterceptDllDriver(char* szSvrName)
  587. {
  588. /************************* 卸载NT驱动的代码******************************
  589. ① 调用OpenSCManager,打开SCM管理器,如果返回NULL,则返回失败,否则继续.
  590. ② 调用OpenService.如果返回NULL,则返回失败,否则继续
  591. ③ 调用DeleteService卸载此项服务.
  592. ④ 成功返回.
  593. ************************************************************************/
  594. bool bRet = false;
  595. SC_HANDLE hServiceMgr=NULL;// SCM管理器的句柄
  596. SC_HANDLE hServiceDDK=NULL;// NT驱动程序的服务句柄
  597. SERVICE_STATUS SvrSta;
  598. sp_dbg_info("start OpenSCManager");
  599. hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  600. if( hServiceMgr == NULL )
  601. {
  602. sp_dbg_info("OpenSCManager() Failed %d!", GetLastError());
  603. bRet = false;
  604. goto BeforeLeave;
  605. }
  606. else
  607. {
  608. sp_dbg_info("OpenSCManager() ok !");
  609. }
  610. hServiceDDK = OpenService(hServiceMgr, szSvrName, SERVICE_ALL_ACCESS);
  611. if(hServiceDDK == NULL)
  612. {
  613. sp_dbg_info("OpenService() Failed %d!", GetLastError());
  614. bRet = false;
  615. goto BeforeLeave;
  616. }
  617. else
  618. {
  619. sp_dbg_info("OpenService() ok !");
  620. }
  621. // 停止驱动程序,如果停止失败,只有重新启动才能,再动态加载。
  622. if(!ControlService(hServiceDDK, SERVICE_CONTROL_STOP , &SvrSta ))
  623. {
  624. sp_dbg_info("ControlService() Failed %d!", GetLastError());
  625. }
  626. else
  627. {
  628. sp_dbg_info("ControlService() ok !");
  629. }
  630. if(!DeleteService(hServiceDDK))
  631. {
  632. sp_dbg_info("DeleteSrevice() Failed %d!", GetLastError());
  633. }
  634. else
  635. {
  636. sp_dbg_info("DelServer:DeleteSrevice() ok !");
  637. }
  638. bRet = true;
  639. BeforeLeave:
  640. if(hServiceDDK)
  641. {
  642. CloseServiceHandle(hServiceDDK); // 服务句柄
  643. }
  644. if(hServiceMgr)
  645. {
  646. CloseServiceHandle(hServiceMgr); // SCM 句柄
  647. }
  648. return bRet;
  649. }
  650. #endif //_WIN32
  651. void DisplayUsage()
  652. {
  653. char szHelp[1024] = { '\0' };
  654. sprintf_s(szHelp, 1024, "\n"
  655. "Usage spshell [--entity <entityName>] [--guardian] [--test] [--debug] [--ipc <pipe|tcp>]\n"
  656. " --entity {entityName} -- 启动指定的实体\n"
  657. " --guardian -- 以后台监控形式运行程序\n"
  658. " --test -- 以测试模式运行程序\n"
  659. " --debug -- 以Debug的模式运行程序\n"
  660. " --kill -- 直接杀死程序相关进程\n"
  661. " --ipc <pipe,tcp> -- pipe: 实体间以管道的方式通信;tcp: 实体间以socket的方式通信\n"
  662. " --version -- 查看相关模块的版本号和生成时间\n"
  663. #ifndef NDEBUG
  664. " --telnet {listern port} -- 在指定端口打开 Telnet,仅在调试版本支持 \n"
  665. #endif
  666. );
  667. //sp_dbg_info(szHelp);
  668. #ifdef _WIN32
  669. MessageBoxA(NULL, szHelp, "Spshell Usage Tip", MB_OK);
  670. #else
  671. printf(szHelp);
  672. #endif //_WIN32
  673. }
  674. const char* GetFullVersionString(bool logFlag = false)
  675. {
  676. static char szVersion[128] = {'\0'};
  677. if (strlen(szVersion) == 0) {
  678. CVersion spbase_version;
  679. GetLibVersion(spbase_version);
  680. sprintf_s(szVersion, 128, "spbase version: %s(build date: %s)%s"
  681. "libtoolkit version: %s",
  682. spbase_version.ToString().GetData(), GetLibBuildDate(), logFlag ? " " : "\n",
  683. toolkit_version_string());
  684. }
  685. return szVersion;
  686. }
  687. sp_cfg_start_args_t* DealWithArgs(int argc, char** argv)
  688. {
  689. int allocedEntitiyLen = 0;
  690. sp_cfg_start_args_t* args = MALLOC_T(sp_cfg_start_args_t);
  691. assert(args);
  692. memset(args, 0, sizeof(sp_cfg_start_args_t));
  693. static struct option spshell_options[] = {
  694. {"entity", required_argument, 0, 'E' },
  695. {"guardian", no_argument, 0, 'G'},
  696. {"test", no_argument, 0, 'T'},
  697. {"debug", no_argument, 0, 'D'},
  698. {"ipc", required_argument, 0, 'I'},
  699. {"shutdown", no_argument, 0, 'S'},
  700. {"kill", no_argument, 0, 'K'},
  701. #ifndef NDEBUG
  702. {"telnet", required_argument, 0, 'N' },
  703. #endif
  704. {"help", no_argument, 0, 'H'},
  705. {"version", no_argument, 0, 'V'},
  706. {0, 0, 0, 0}
  707. };
  708. int spshell_index = 0;
  709. int c;
  710. while ((c = getopt_long(argc, argv, "E:GTDI:?", spshell_options, &spshell_index)) != EOF) {
  711. switch (c) {
  712. case 'E':
  713. {
  714. //sp_dbg_info("start specified entity: %s", optarg);
  715. if (optarg != NULL) {
  716. const int len = strlen(optarg);
  717. if (args->start_entities == NULL || len + strlen(args->start_entities) + 2 /*;\0*/ >= allocedEntitiyLen) {
  718. if (args->start_entities == NULL) {
  719. assert(allocedEntitiyLen == 0);
  720. allocedEntitiyLen = 128;
  721. args->start_entities = CALLOC_T(allocedEntitiyLen, char);
  722. if (NULL == args->start_entities) {
  723. exit(-1);
  724. }
  725. }
  726. else {
  727. assert(allocedEntitiyLen != 0);
  728. const int newLen = allocedEntitiyLen + len + 32;
  729. char* newAlloc = CALLOC_T(newLen, char);
  730. if (NULL == newAlloc) {
  731. exit(-1);
  732. }
  733. memset(newAlloc, '\0', sizeof(char) * newLen);
  734. strcpy_s(newAlloc, newLen, args->start_entities);
  735. FREE(args->start_entities);
  736. args->start_entities = newAlloc;
  737. allocedEntitiyLen = newLen;
  738. }
  739. }
  740. strcat(args->start_entities, optarg);
  741. strcat(args->start_entities, ";");
  742. }
  743. }
  744. break;
  745. case 'G':
  746. //sp_dbg_info("run spshell as guardian mode!");
  747. args->guardian_mode = 1;
  748. break;
  749. case 'D':
  750. //sp_dbg_info("run spshell as debug mode!");
  751. args->debug_mode = 1;
  752. break;
  753. case 'T':
  754. //sp_dbg_info("run spshell as test mode!");
  755. args->test_mode = 1;
  756. break;
  757. case 'I':
  758. //sp_dbg_info("run spshell with specified ipc method: %s", optarg);
  759. if (optarg) {
  760. if (strnicmp(optarg, "tcp", strlen("tcp")) == 0)
  761. args->ipc_type = 1;
  762. }
  763. break;
  764. #ifndef NDEBUG
  765. case 'N':
  766. if (optarg) {
  767. int nPort = 0;
  768. if (0 < sscanf(optarg, "%d", &nPort))
  769. args->telnet_port = nPort;
  770. }
  771. break;
  772. #endif
  773. case 'K':
  774. {
  775. //sp_dbg_info("terminate spshell!");
  776. char* relate_processes[] = {
  777. #ifdef _WIN32
  778. "spshell.exe", "sphost.exe", "guardian.exe"
  779. #else
  780. "spshell", "sphost", "guardian"
  781. #endif //_WIN32
  782. };
  783. osutil_terminate_related_process(relate_processes, sizeof(relate_processes) / sizeof(relate_processes[0]));
  784. exit(0);
  785. }
  786. break;
  787. case 'V':
  788. {
  789. #ifdef _WIN32
  790. MessageBoxA(NULL, GetFullVersionString(), "Spshell", MB_OK);
  791. #else
  792. printf("%s\n", GetFullVersionString());
  793. #endif //_WIN32
  794. exit(0);
  795. break;
  796. }
  797. break;
  798. case 'H':
  799. case '?':
  800. default:
  801. DisplayUsage();
  802. exit(0);
  803. break;
  804. }
  805. }
  806. if (optind < argc) {
  807. //sp_dbg_warn("non-option ARGV-elements: ");
  808. while (optind < argc) {
  809. //sp_dbg_warn("\t%s", argv[optind++]);
  810. }
  811. }
  812. if (args && args->start_entities != 0) {
  813. args->start_entities[strlen(args->start_entities) - 1] = '\0';
  814. }
  815. return args;
  816. }
  817. int main(int argc, char** argv)
  818. {
  819. sp_cfg_start_args_t* args = DealWithArgs(argc, argv);
  820. #if (0 && defined(_WIN32))
  821. char szProcessID[12];
  822. sprintf(szProcessID, "%u", GetCurrentProcessId());
  823. MessageBoxA(NULL, szProcessID, "", MB_OK);
  824. #endif //_WIN32
  825. if (args->debug_mode)
  826. { //open wlog
  827. SP::Perf::LeakDetector leakInstance;
  828. WLog_initRVC("SpShell");
  829. }
  830. #ifdef _WIN32
  831. _CrtSetDebugFillThreshold(0);
  832. #endif //_WIN32
  833. sp_dbg_init("SpShell");
  834. sp_dbg_info("===================SpShell start=====================");
  835. if (argc > 1) {
  836. char cmdline[1024] = { '\0' };
  837. for (int i = 0; i < argc; ++i) {
  838. sprintf_s(cmdline, 1024, "%s %s", cmdline, argv[i]);
  839. }
  840. sp_dbg_info(cmdline);
  841. }
  842. sp_dbg_info(GetFullVersionString(true));
  843. char proc1[64] = { '\0' };
  844. char proc2[64] = { '\0' };
  845. #ifdef _WIN32
  846. strcpy(proc1, "SpShell.exe");
  847. strcpy(proc2, "SpHost.exe");
  848. #else
  849. strcpy(proc1, "spshell");
  850. strcpy(proc2, "sphost");
  851. #endif //_WIN32
  852. char* arrProcName[] = { proc1, proc2 };
  853. //DetectDuplicateInstance
  854. if(!osutil_detect_unique_app(&arrProcName[0], sizeof(arrProcName) / sizeof(arrProcName[0])))
  855. {
  856. sp_dbg_fatal("detect duplicate spshell/sphost process, abort cur boot !!!");
  857. Sleep(10000);
  858. sp_dbg_term();
  859. return -200;
  860. }
  861. if (!IsProcessRunAsAdmin())
  862. {
  863. #ifdef _WIN32
  864. MessageBox(NULL, "Need run with Administrator privilege!", "Error", MB_OK);
  865. #else
  866. sp_dbg_fatal("current process need run with administrator or root privilege !!!");
  867. #endif //_WIN32
  868. Sleep(10000);
  869. sp_dbg_term();
  870. return -201;
  871. } else {
  872. sp_dbg_info("current process has been run with administrator or root privilege.");
  873. }
  874. #ifdef _WIN32
  875. // 设置防火墙注册表配置
  876. AddFirewallRulesEx();
  877. // 自动隐藏状态栏
  878. //AutoHideTaskBar(true);
  879. #endif //_WIN32
  880. #ifdef _WIN32
  881. setlocale(LC_ALL, "chs");
  882. #else
  883. if (NULL == setlocale(LC_ALL, "zh_CN.UTF-8")) {
  884. //zh_CN.UTF-8 zh_CN.GBK
  885. sp_dbg_error("setlocale failed: %s", strerror(errno));
  886. }
  887. sp_dbg_info("测试中文字符:%s", "招商银行");
  888. #endif //_WIN32
  889. SetEnvPath();
  890. #ifdef _WIN32
  891. SetWorkingSet();
  892. SetUnhandledExceptionFilter(&SuppressError);
  893. DisableSetUnhandledExceptionFilter();
  894. #endif //_WIN32
  895. sp_dbg_info("basic config success");
  896. #ifdef _WIN32
  897. // 检测是否Win8及64位
  898. OSVERSIONINFO ver = {};
  899. ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  900. GetVersionEx(&ver);
  901. bool bWin8 = (ver.dwMajorVersion >= 7 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2));
  902. SYSTEM_INFO sysInfo = {};
  903. GetNativeSystemInfo(&sysInfo);
  904. bool bX64 = (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
  905. sp_dbg_info("OS version: %s %d.%d.%d ", bX64 ? "windows 64" : "windows 32", ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber);
  906. // 关闭WebBrowser渲染模式
  907. //DisableWebBrowserRenderMode(bX64);
  908. // 屏蔽CharmBar
  909. if (bWin8 && !DisableWindowsCharmBar(bX64))
  910. {
  911. Sleep(10000);
  912. return -300;
  913. }
  914. //#ifndef _DEBUG
  915. SetErrorMode(SEM_FAILCRITICALERRORS);
  916. //#endif
  917. #endif //_WIN32
  918. auto rc = app_init(args);
  919. FREE(args);
  920. if (rc == 0)
  921. {
  922. #ifdef _WIN32
  923. WebcamMicrophoneAuthorize(bX64);
  924. #endif //_WIN32
  925. rc = app_run();
  926. app_term();
  927. }
  928. else
  929. {
  930. sp_dbg_error("======================================================");
  931. sp_dbg_error("!!!!!! Startup failed, get more detail information from dbg/spshell !!!!!!");
  932. sp_dbg_error("======================================================");
  933. Sleep(10000);
  934. }
  935. #ifdef _WIN32
  936. if (bWin8 && !bX64) {
  937. EnableCharmbar();
  938. }
  939. // 显示状态栏
  940. //AutoHideTaskBar(false);
  941. #endif //_WIN32
  942. sp_dbg_term();
  943. return rc;
  944. }
  945. #ifdef _WIN32
  946. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
  947. {
  948. return main(__argc, __argv);
  949. }
  950. #endif //_WIN32