#include "stdafx.h" #include "ResourceWatcherFSM.h" #include "DeviceBaseClass.h" #include #include #include #include #include "fileutil.h" #include #include "CommEntityUtil.hpp" #include "SpUtility.h" #include "RestfulFunc.h" #include #include #include "ResourceWatcher_UserCode.h" #ifdef RVC_OS_LINUX #include #include #include #include #include #include "publicFunExport.h" #include "toolkit.h" #include "iniutil.h" #include "osutil.h" #else #include #include #include #include #include #include #include "memutil.h" #include "array.h" #include #include #include #include #include #include #include //网络检测添加 #include #include #include "Mmdeviceapi.h" #include "Propidl.h" #include "Functiondiscoverykeys_devpkey.h" #pragma comment(lib, "pdh.lib") #pragma comment(lib,"winmm.lib" ) #pragma comment(lib, "shell32.lib") #pragma comment(lib, "Wintrust.lib") #pragma comment(lib, "crypt32.lib") #pragma comment(lib, "wlanapi.lib") #endif //硬件信息搜集参数 #define DEFAULT_HARDWARE_CHECK_TIME 60 * 1000 //CPU、内存扫描默认间隔,1分钟 #define TIMER_HARDWARE_CHECK 2 //硬盘扫描 #define DEFAULT_DISK_CHECK_TIME 4 * 60 * 60 * 1000 //硬盘默认4小时扫描一次 #define TIMER_DISK_CHECK 3 //保留版本数目 #define DEFAULT_VERSION_SAVED_COUNT 5 #define MAX_VERSION_PATH 256 //一天的秒数,用于计算文件时间 const int SECONDS_OF_DAY = 60 * 60 * 24; const int VIDEO_DEFAULT_BACKDAYS = 30; #ifdef RVC_OS_LINUX #define PROCESS_ITEM 14 //进程CPU信息读取位置参数 const int MAX_MAINLINK_CHECK_TIME = 5000; const int TIMER_MAINLINK_CHECK = 4; #else const int TIMER_ID_CLEARVIDEO_ENHANCE = 1; const int THOUSAND = 1024; const int MILLION = 1048576; #endif // RVC_OS_LINUX static int hardwareCheckTime = 60 * 1000; //初始化硬件检测间隔 static int hardwareCheckFlag = 1; static int cpuWarnTime = 0; static int cpuWarnThreshold = 10; static int memWarnTime = 0; static int memWarnThreshold = 10; //初始化CUP、内存告警阈值次数 static int diskCheckTime = 4 * 60 * 60 * 1000; //初始化硬盘检测间隔 static int diskCheckFlag = 1; #define DIV (1024 * 1024) #define DAY_DIV (24 * 60 * 60) #define HOURS_DIV (60 * 60) #define MINUS_DIV (60) #ifndef RVC_OS_LINUX #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) #define SafeDeleteArraySize(pData) { if(pData){delete []pData;pData=NULL;} } #endif // !RVC_OS_LINUX template class TimerOutHelper : public ITimerListener { public: typedef void (T::* FuncTimer)(void* pUserdata); TimerOutHelper(T* p, FuncTimer pTimerFunc, void* pData, bool bDeleteSelf = false) : m_pObject(p), m_pUserData(pData), m_pTimer(pTimerFunc), m_bDeleteSelf(bDeleteSelf) { } virtual void OnTimeout(DWORD dwTimerID) { (m_pObject->*m_pTimer)(m_pUserData); if (m_bDeleteSelf) delete this; } private: void* m_pUserData; T* m_pObject; FuncTimer m_pTimer; bool m_bDeleteSelf; }; ResourceWatcherFSM::ResourceWatcherFSM(void) :m_strTerminalNo(true), m_bFirstRunAfterBoot(FALSE), m_cpuTop(0) { #ifdef RVC_OS_WIN m_forceStartupWithExeFlag = 0; m_iNonSignedTotal = 0; m_bNeedForceDiskCheck = false; m_DoneDetectAutostart = true; #endif // RVC_OS_WIN } ResourceWatcherFSM::~ResourceWatcherFSM(void) { } void ResourceWatcherFSM::s0_on_entry() { LOG_FUNCTION(); #if defined(RVC_OS_WIN) this->PostEventFIFO(new RunEvent()); BOOL fInstallBySetup(FALSE); ErrorCodeEnum rc = DetectVTMInstalledBySetup(fInstallBySetup); if (Error_Succeed == rc && !fInstallBySetup) { GetEntityBase()->GetFunction()->PostThreadPoolTask(new CreateLinkTask(this)); } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("detect install type return %s, setup type: %d", SpStrError(rc), fInstallBySetup); } #endif //RVC_OS_WIN } unsigned int ResourceWatcherFSM::s0_on_event(FSMEvent* e) { LOG_FUNCTION(); unsigned int unRes = 0; switch (e->iEvt) { case USER_EVT_RUN: { e->SetHandled(); } break; default: { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Unexpecetd Event(%d)", e->iEvt); } break; } return unRes; } void ResourceWatcherFSM::s0_on_exit() { } void ResourceWatcherFSM::s1_on_entry() { LOG_FUNCTION(); } unsigned int ResourceWatcherFSM::s1_on_event(FSMEvent* e) { LOG_FUNCTION(); unsigned int unRes = 0; e->SetHandled(); return unRes; } void ResourceWatcherFSM::s1_on_exit() { } void ResourceWatcherFSM::s2_on_entry() { LOG_FUNCTION(); } unsigned int ResourceWatcherFSM::s2_on_event(FSMEvent* e) { LOG_FUNCTION(); unsigned int unRes = 0; switch (e->iEvt) { case USER_EVT_RUN: { e->SetHandled(); } break; } return unRes; } void ResourceWatcherFSM::s2_on_exit() { } void ResourceWatcherFSM::s3_on_entry() { LOG_FUNCTION(); } unsigned int ResourceWatcherFSM::s3_on_event(FSMEvent* e) { unsigned int unRes = 0; switch (e->iEvt) { case USER_EVT_RUN: { e->SetHandled(); } break; } return unRes; } void ResourceWatcherFSM::s3_on_exit() { } #ifdef RVC_OS_LINUX bool ResourceWatcherFSM::GetMonitorInfo(CSimpleStringA& outInfo) { std::string sucContent, failedContent; CSimpleStringA strCmd("xrandr | grep \" connected\" | sed -e \"s/\([A-Z0-9]\+\) connected.*/\1/\""); bool ret = SP::Module::Util::ShellExecute(strCmd.GetData(), sucContent, failedContent); //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("{%s}:{%s}{%s}", strCmd.GetData(), sucContent.c_str(), failedContent.c_str()); std::string msg = SP::Utility::ToTrim(sucContent); SP::Utility::replaceInPlace(msg, "\n", "|"); outInfo = msg.c_str(); return ret; } #endif // RVC_OS_LINUX //首页状态变化时触发的功能 void ResourceWatcherFSM::TriggerAtStatusChanged(bool bMStatus) { if (firstMpage)//首次进入首页 { firstMpage = false; CSmartPointer spRunConfig; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spRunConfig); GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "HardwareCheckTime", hardwareCheckTime); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "HardwareCheckFlag", hardwareCheckFlag); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "DiskCheckTime", diskCheckTime); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "DiskCheckFlag", diskCheckFlag); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "CpuTooHighPercent", m_cpuHighPercent); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "CpuWarnThreshold", cpuWarnThreshold); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "MemoryTooHighPercent", m_memHighPercent); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "MemWarnThreshold", memWarnThreshold); spCtSettingConfig->ReadConfigValueInt("ResourceWatcher", "HardDiskTooHighPercent", m_diskHighPercent); spCtSettingConfig->ReadConfigValueInt(m_pEntity->GetEntityName(), "VerifySignature", m_iVerify); #if defined(RVC_OS_WIN) if (m_iVerify == 1) {//文件签名校验 DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Verify digitsign..."); VerifyDigitSignTask* task = new VerifyDigitSignTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); } #endif //RVC_OS_WIN if (hardwareCheckTime <= 0) { //非法数值情况下设置为默认一分钟 hardwareCheckTime = DEFAULT_HARDWARE_CHECK_TIME; } void* pTmpData = NULL; ITimerListener* pListener = new TimerOutHelper(this, &ResourceWatcherFSM::HardwareInfoTimer, pTmpData); GetEntityBase()->GetFunction()->SetTimer(TIMER_HARDWARE_CHECK, pListener, hardwareCheckTime); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Set Hardware Timer!"); if (diskCheckFlag > 0) { GetSystemDiskStatus(); //仅启动时检测一次硬盘状态即可 } if (diskCheckTime <= 0) { diskCheckTime = DEFAULT_DISK_CHECK_TIME; } void* pTmpData2 = NULL; ITimerListener* pListener2 = new TimerOutHelper(this, &ResourceWatcherFSM::DiskCheckTimer, pTmpData2); GetEntityBase()->GetFunction()->SetTimer(TIMER_DISK_CHECK, pListener2, diskCheckTime); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Set DISK CHECK Timer!"); //集中配置额外加的清理逻辑 CenterSettingDeleteTask* centerSettingDeleteTask = new CenterSettingDeleteTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(centerSettingDeleteTask); //终端默认的自动清理逻辑 AutoDeleteFilesTask* autoDeleteTask = new AutoDeleteFilesTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(autoDeleteTask); #if defined(RVC_OS_LINUX) if (m_bFirstRunAfterBoot) { UINT sysVer = 0; UploadSysVersionInfo(sysVer); ConfirmWindowEffectHasBeenOpen(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("fetch os version: %u", sysVer); if (1031 < sysVer) { ConfirmDDEClipboardDisable(); ConfirmNotificationCenterDisable(); } else { RecoverDDEClipboardEnable(); } GetEntityBase()->GetFunction()->PostThreadPoolTask(new DetectSoftwareInstallStatusTask(this)); GetEntityBase()->GetFunction()->PostThreadPoolTask(new UploadMonitorInfoTask(this)); AlarmSystemBasicInfo(); } #endif //RVC_OS_LINUX } } ErrorCodeEnum ResourceWatcherFSM::OnInit() { firstMpage = true; //是否首次进入首页 ErrorCodeEnum erroCode = Error_Succeed; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Complied at: %s %s", __DATE__, __TIME__); CSmartPointer spRunConfig; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spRunConfig); GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); erroCode = GetEntityBase()->GetFunction()->GetSystemStaticInfo(m_RvcSysinfo); m_strTerminalNo = m_RvcSysinfo.strTerminalID; m_bFirstRunAfterBoot = DetectIsFirstRunAtBoot(); if (m_bFirstRunAfterBoot) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("First time to run after system boot."); } if (m_bFirstRunAfterBoot) { #if defined(RVC_OS_WIN) //GetSystemMetrics (SM_CMONITORS) 计数仅显示可见的显示器 const int screenNums = GetSystemMetrics(SM_CMONITORS); const int aimScreenNums4Stand2S = 2; const int aimScreenNums4Other = 1; if (0 == m_RvcSysinfo.strMachineType.Compare("RVC.Stand2S", true) && screenNums != aimScreenNums4Stand2S) { LogWarn(Severity_Low, Error_Unexpect, LOG_RESOURCEWATCHER_LACK_OF_MONITOR , CSimpleStringA::Format("{\"subject\":\"screen_count\",\"machine_type\":\"%s\",\"expect\":%d,\"actual\":%d}" , m_RvcSysinfo.strMachineType.GetData(), aimScreenNums4Stand2S, screenNums)); } else if (0 != m_RvcSysinfo.strMachineType.Compare("RVC.Stand2S", true) && screenNums != aimScreenNums4Other) { LogWarn(Severity_Low, Error_Unexpect, LOG_RESOURCEWATCHER_LACK_OF_MONITOR , CSimpleStringA::Format("{\"subject\":\"screen_count\",\"machine_type\":\"%s\",\"expect\":%d,\"actual\":%d}" , m_RvcSysinfo.strMachineType.GetData(), aimScreenNums4Other, screenNums)); } #endif //RVC_OS_WIN } spCtSettingConfig->ReadConfigValueInt(m_pEntity->GetEntityName(), "DisplayCnt", m_iNonSignedDisplay); if (m_iNonSignedDisplay <= 0) m_iNonSignedDisplay = 10; spRunConfig->ReadConfigValueInt("WarnRecord", "disk", m_diskLastWarnHour); return Error_Succeed; } ErrorCodeEnum ResourceWatcherFSM::OnExit() { #ifdef RVC_OS_LINUX GetEntityBase()->GetFunction()->KillTimer(TIMER_HARDWARE_CHECK); #endif // RVC_OS_LINUX return Error_Succeed; } void ResourceWatcherFSM::AfterInit() { #if defined(RVC_OS_WIN) if (m_bFirstRunAfterBoot) { DetectAutoStartupCover(); DetectWallpaperAndWarn(); ClearDesktopFileTask* task = new ClearDesktopFileTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task); } DetectVersionHasChangedAndWarnCover(); #endif //RVC_OS_WIN } void ResourceWatcherFSM::LinkDetect(int detectType, const char* url, bool& status, unsigned int& delay, int warnFlag) { string tUrl = url; string host = "http://"; int flag = 0; unsigned int tInterval = 0; string msg; if (tUrl.find("http") == string::npos) { tUrl = host + tUrl; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Check url:[%s].", tUrl.c_str()); ULLINT begin, end; begin = SP::Module::Comm::RVCGetTickCount(); int curFlag = HttpProbe(tUrl, msg, 5); end = SP::Module::Comm::RVCGetTickCount(); tInterval = end - begin; if (curFlag > 0 && curFlag < 400) { flag = true; } else { flag = false; } if (flag == false) { status = false; } else { status = true; } delay = tInterval > 0 ? tInterval:1; } ErrorCodeEnum ResourceWatcherFSM::BizLinkDetect( SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); ErrorCodeEnum ec = Error_Succeed; int detectType = ctx->Req.protocol; CSimpleStringA url = ctx->Req.bizLink; bool linkStatus = false; unsigned int delay = 0; LinkDetect(detectType, url.GetData(), linkStatus, delay); ctx->Ans.bizLinkStatus = linkStatus; ctx->Ans.bizLinkDelayMS = delay; ctx->Ans.intParam = 0; CSimpleStringA warn; if (!linkStatus) { warn = CSimpleStringA::Format("BizLink disconnected[%s].", url.GetData()); } else { warn = CSimpleStringA::Format("BizLink connected[%s], Delay time [%d]ms.", url.GetData(), delay); } LogWarn(Severity_Low, Error_Param, LOG_WARN_BIZLINK_CONNECT_CHECK, warn.GetData()); if (ctx != NULL) { ctx->Answer(ec); } return ec; } //通过集中配置额外执行的清理策略 void ResourceWatcherFSM::CenterSettingDelete() { string p; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); CSimpleStringA upPath(""), tempPath(""), tPath(""), upgradePath(""); spCtSettingConfig->ReadConfigValue("ResourceWatcher", "DocumentCleanPath", tempPath); if (tempPath.GetLength() == 0) { return; } ErrorCodeEnum erroCode = Error_Succeed; CSmartPointer pFunc = GetEntityBase()->GetFunction(); CSmartPointer spConfigRun; //判断是否需要被清理 erroCode = pFunc->OpenConfig(Config_Run, spConfigRun); if (erroCode != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Open Run Config failed"); return; } int nLastTaskTime = 0; int nLstFlag = 0; bool bFailFlag = false; CSimpleStringA optFileName(""); UINT64 utVersion = 0; spConfigRun->ReadConfigValueHexInt("DeleteDocumentTask", "OptVer", utVersion); spConfigRun->ReadConfigValue("DeleteDocumentTask", "DocumentName", optFileName); spConfigRun->ReadConfigValueInt("DeleteDocumentTask", "LastCondi", nLstFlag); spConfigRun->ReadConfigValueInt("DeleteDocumentTask", "LastTime", nLastTaskTime); CVersion optVer(utVersion); SYSTEMTIME stTaskTime = CSmallDateTime(nLastTaskTime).ToSystemTime(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("LastTime<%04d-%02d-%02d %02d:%02d:%02d>: OptVer: %s, LastCondi: %d", stTaskTime.wYear, stTaskTime.wMonth, stTaskTime.wDay, stTaskTime.wHour, stTaskTime.wMinute, stTaskTime.wSecond, (LPCTSTR)optVer.ToString(), nLstFlag); if (optVer.IsValid() && optVer == m_RvcSysinfo.InstallVersion && !nLstFlag && optFileName == tempPath) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Certain document cleaning has been done before."); return; } //执行清理逻辑 upPath = tempPath; int nDelSuc = 0, nDelFail = 0, nFileCount = 0; nFileCount = ProcessFileDelete(upPath.GetData(), nDelSuc, nDelFail, false); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Process result(%s): count(%d), suc(%d), failed(%d).", upPath.GetData(), nFileCount, nDelSuc, nDelFail); if (nDelFail != 0) { bFailFlag = true; //break; } nLstFlag = bFailFlag ? 1 : 0; spConfigRun->WriteConfigValueHexInt("DeleteDocumentTask", "OptVer", m_RvcSysinfo.InstallVersion.GetVersion64()); spConfigRun->WriteConfigValue("DeleteDocumentTask", "DocumentName", tempPath); spConfigRun->WriteConfigValueInt("DeleteDocumentTask", "LastCondi", nLstFlag); spConfigRun->WriteConfigValue("DeleteDocumentTask", "LastTime", (LPCTSTR)CSimpleStringA::Format("0x%08X", (DWORD)CSmallDateTime::GetNow())); if (!bFailFlag) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_FILE_DELETE_SUC, CSimpleStringA::Format("Delete files in [%s] success", tempPath.GetData())); } } time_t ResourceWatcherFSM::GetPathTimeSeconds(const char* inPath) { if (!inPath) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetPathFileDays PATH = NULL.", inPath); return 0; } time_t lCreateTime = 0; //int reTimes = 0; #ifdef RVC_OS_WIN struct _finddata_t fileinfo;//文件信息读取结构 string p; long hFile = _findfirst(inPath, &fileinfo); if (hFile == -1L) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Get [%s] fileinfo failed. GLE = %u.", inPath, GetLastError()); return 0; } lCreateTime = fileinfo.time_write; //文件最后修改时间 _findclose(hFile); #else struct stat stFile; if (stat(inPath, &stFile) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("[%s] Failed to get file stats. GLE=%d.", inPath, GetLastError()); return 0; } lCreateTime = stFile.st_mtime; //文件状态最后修改时间 #endif // RVC_OS_WIN //reTimes = lCreateTime; //文件时间 return lCreateTime; } //所有文件删除功能都用这个函数来处理 //bool delDir:控制是否将目录也一并删除,false 保留目录, true 删除目录 //int saveBackDay:保存多少天内的文件, 默认参数,默认值为0,即不保存。(delDir = true时,该参数强制为0) int ResourceWatcherFSM::ProcessFileDelete(LPCTSTR lpszPath, int& nDelSucCnt, int& nDelFailedCnt, bool delDir, unsigned int saveBackDay) { if (delDir == true) //若要删除目录,则不保留任何文件 { saveBackDay = 0; } int fileCnt = 0; char* searchFilePath = new char[MAX_PATH]; char* tempFilePath = new char[MAX_PATH]; if (searchFilePath == NULL || tempFilePath == NULL) { if (searchFilePath) delete[] searchFilePath; if (tempFilePath) delete[] tempFilePath; searchFilePath = NULL; tempFilePath = NULL; return fileCnt; } ZeroMemory(searchFilePath, MAX_PATH); ZeroMemory(tempFilePath, MAX_PATH); #ifdef RVC_OS_LINUX int fileLength = strlen(lpszPath); struct stat st; if (stat(lpszPath, &st) == -1) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("[%s] Failed to get file stats.", lpszPath); nDelSucCnt++; return fileCnt; } if (!S_ISDIR(st.st_mode)) {//单文件处理 if (saveBackDay != 0) { time_t lSystemTime; time(&lSystemTime); time_t fileTime = GetPathTimeSeconds(lpszPath); //获取文件的最后改动时间 int delDays = (lSystemTime - fileTime) / SECONDS_OF_DAY; if (delDays < saveBackDay) // 未达到需要清理的天数阈值,无需清理 { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Files 存留天数[%d], 删除阈值[%u],无需清理.", (int)delDays, saveBackDay); return fileCnt; } } if (RemoveFileA(lpszPath) == true) { nDelSucCnt++; fileCnt++; } else { nDelFailedCnt++; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A08").setAPI("DeleteFiles")("RemoveFileA [%s] failed, GLE = %u.", tempFilePath, errno); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_FILE_DELETE_FAILED, CSimpleStringA::Format("RemoveFileA [%s] failed, GLE = %u.", tempFilePath, errno)); } if (searchFilePath) delete[] searchFilePath; if (tempFilePath) delete[] tempFilePath; searchFilePath = NULL; tempFilePath = NULL; return fileCnt; } DIR* d = opendir(lpszPath); if (!d) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("opendir failed: %d.", errno); if (searchFilePath) delete[] searchFilePath; if (tempFilePath) delete[] tempFilePath; searchFilePath = NULL; tempFilePath = NULL; nDelFailedCnt++; return fileCnt; } struct dirent* dp = NULL; while ((dp = readdir(d)) != NULL) { if ((!strcmp(dp->d_name, ".")) || (!strcmp(dp->d_name, ".."))) { continue; } strcpy(tempFilePath, lpszPath); if (strlen(tempFilePath) + strlen(dp->d_name) + 3 >= MAX_PATH) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("filePath is too long for current."); continue; } strcat(tempFilePath, "/"); strcat(tempFilePath, dp->d_name); stat(tempFilePath, &st); if (saveBackDay != 0) { time_t lSystemTime; time(&lSystemTime); time_t fileTime = GetPathTimeSeconds(tempFilePath); //获取文件的最后改动时间 int delDays = (lSystemTime - fileTime) / SECONDS_OF_DAY; if (delDays < saveBackDay) // 未达到需要清理的天数阈值,无需清理 { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Dir[%s], 存留天数[%d], 删除阈值[%u],无需清理.", tempFilePath, (int)delDays, saveBackDay); continue; } } int tDelSucCnt = 0, tDelFailedCnt = 0; fileCnt += ProcessFileDelete((LPCTSTR)tempFilePath, tDelSucCnt, tDelFailedCnt, true); //子目录要清理 if (tDelFailedCnt != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A08").setAPI("DeleteFiles")("rm(%s) failed, GLE = %u.", (LPCTSTR)tempFilePath, errno); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_FILE_DELETE_FAILED, CSimpleStringA::Format("rm(%s) failed, GLE = %u.", (LPCTSTR)tempFilePath, errno)); nDelSucCnt += tDelSucCnt; nDelFailedCnt += tDelFailedCnt; return fileCnt; } nDelSucCnt += tDelSucCnt; } closedir(d); #else CSimpleStringA inPath = lpszPath; inPath.Append("\\*"); // "D:aaa\bbb\ccc\* " 匹配目录下的所有文件和文件夹 int fileLength = inPath.GetLength(); WIN32_FIND_DATA wfd; HANDLE hFind; hFind = FindFirstFile(inPath.GetData(), &wfd); //单文件操作 if (hFind == INVALID_HANDLE_VALUE) // 非文件夹 (inPath "D:aaa\bbb\ccc\* "格式的情况下,如果前面是文件,会找不到匹配) { if (saveBackDay != 0) { //读取文件时间 time_t lSystemTime; time(&lSystemTime); time_t fileTime = GetPathTimeSeconds(lpszPath); //获取文件的最后改动时间 int delDays = (lSystemTime - fileTime) / SECONDS_OF_DAY; if (delDays < saveBackDay) // 未达到需要清理的天数阈值,无需清理 { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("存留天数[%d], 删除阈值[%u],无需清理.", (int)delDays, saveBackDay); return fileCnt; } } if (DeleteFile(lpszPath) == true) { nDelSucCnt++; fileCnt++; } else { nDelFailedCnt++; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A08").setAPI("DeleteFiles") ("Delete [%s] failed, GLE = %u.", lpszPath, GetLastError()); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_FILE_DELETE_FAILED, CSimpleStringA::Format("RemoveFileA [%s] failed, GLE = %u.", lpszPath, errno)); } if (searchFilePath) delete[] searchFilePath; if (tempFilePath) delete[] tempFilePath; searchFilePath = NULL; tempFilePath = NULL; return fileCnt; } //文件夹操作 do { if (wfd.cFileName[0] != '.') { strcpy_s(tempFilePath, MAX_PATH, inPath.GetData()); tempFilePath[fileLength - 1] = '\0'; if (strlen(tempFilePath) + strlen(wfd.cFileName) + 3 >= MAX_PATH) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("filePath is too long for current."); } else { strcat_s(tempFilePath, MAX_PATH, wfd.cFileName); //"D:aaa\bbb\ccc\fileName" if (saveBackDay != 0) { time_t lSystemTime; time(&lSystemTime); time_t fileTime = GetPathTimeSeconds(tempFilePath); //获取文件的最后改动时间 if (fileTime == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get file time (%s) failed. skip clean", (LPCTSTR)tempFilePath); nDelFailedCnt++; continue; } int delDays = (lSystemTime - fileTime) / SECONDS_OF_DAY; if (delDays < saveBackDay) // 未达到需要清理的天数阈值,无需清理 { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Dir[%s], 存留天数[%d], 删除阈值[%u],无需清理.", tempFilePath, (int)delDays, saveBackDay); continue; } } int tDelSucCnt = 0, tDelFailedCnt = 0; fileCnt += ProcessFileDelete((LPCTSTR)tempFilePath, tDelSucCnt, tDelFailedCnt, true); //子目录要删除 if (tDelFailedCnt != 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A08").setAPI("DeleteFiles") ("rm(%s) failed, GLE = %u.", (LPCTSTR)tempFilePath, GetLastError()); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_FILE_DELETE_FAILED, CSimpleStringA::Format("RemoveFileA [%s] failed, GLE = %u.", (LPCTSTR)tempFilePath, errno)); nDelFailedCnt += tDelFailedCnt; return fileCnt; } nDelFailedCnt += tDelFailedCnt; nDelSucCnt += tDelSucCnt; } } } while (FindNextFileA(hFind, &wfd)); FindClose(hFind); #endif // RVC_OS_LINUX if (delDir) //删除目录 { #ifdef RVC_OS_WIN RemoveDirectoryA(lpszPath); #else RemoveDirRecursive(lpszPath); #endif } if (searchFilePath) delete[] searchFilePath; if (tempFilePath) delete[] tempFilePath; searchFilePath = NULL; tempFilePath = NULL; return fileCnt; } //终端默认执行的终端清理策略 void ResourceWatcherFSM::AutoDeleteFiles() { CSmartPointer pFunc = GetEntityBase()->GetFunction(); CSmartPointer spConfig; pFunc->OpenConfig(Config_CenterSetting, spConfig); //判断是否升级完毕,未完成升级不进行删除任务 CSimpleStringA strRunInfo, strStartTime; if (m_pEntity->GetFunction()->GetPath("RunInfo", strRunInfo) == Error_Succeed) { strStartTime = strRunInfo + SPLIT_SLASH_STR + "runcfg" + SPLIT_SLASH_STR + "starttime.dat"; if (!ExistsFileA(strStartTime.GetData())) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("upgrade prpcess done, try to delete version files.");//完成升级过程,通过 } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("upgrade process is not end ,should not delete files."); return;//升级未完成,不进行删除 } } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("upgrade process is not end ,get runinfo path error, should not version files."); return;//失败,继续等待 } //清理版本相关文件 DeleteVersionPackage(); //清理录像文件 DeleteVideoFiles(); return; } //终端升级后会执行版本清理功能 包含dump和 upgaraded清理 BOOL ResourceWatcherFSM::DeleteVersionPackage() { ErrorCodeEnum erroCode = Error_Succeed; CSmartPointer pFunc = GetEntityBase()->GetFunction(); CSmartPointer spConfigRun; CSmartPointer spConfig; CSystemStaticInfo info; if (pFunc->GetSystemStaticInfo(info) != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Get system static info error"); return FALSE; } //清理执行成功与否的判断变量 int nLastTaskTime = 0; int nLstFailed = 0; int nDelCount = 0; UINT64 utVersion = 0; pFunc->OpenConfig(Config_CenterSetting, spConfig); pFunc->OpenConfig(Config_Run, spConfigRun); spConfigRun->ReadConfigValueHexInt("VersionClear", "OptVer", utVersion); spConfigRun->ReadConfigValueInt("VersionClear", "DelVerCnt", nDelCount); spConfigRun->ReadConfigValueInt("VersionClear", "LastCondi", nLstFailed); //失败标志 spConfigRun->ReadConfigValueInt("VersionClear", "LastTime", nLastTaskTime); CVersion optVer(utVersion); SYSTEMTIME stTaskTime = CSmallDateTime(nLastTaskTime).ToSystemTime(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("LastTime<%04d-%02d-%02d %02d:%02d:%02d>: OptVer: %s, LastFailed: %d", stTaskTime.wYear, stTaskTime.wMonth, stTaskTime.wDay, stTaskTime.wHour, stTaskTime.wMinute, stTaskTime.wSecond, (LPCTSTR)optVer.ToString(), nLstFailed); //判断是否需要执行清理任务,若此版本之前成功清理过则不再继续执行后续操作 if (optVer.IsValid() && optVer == info.InstallVersion && !nLstFailed) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("VersionPackage cleaning has been done before."); return TRUE; } //-------------------------------------------------------------------------------------------- //版本清理中默认进行upgrade清理 int closeUpgradeClear = 0; spConfig->ReadConfigValueInt("ResourceWatcher", "CloseUpgradeClear", closeUpgradeClear); if (!closeUpgradeClear) { //删除rvc/Upgraded目录下的文件 CSimpleStringA upPath; ErrorCodeEnum upError = pFunc->GetPath("Upgraded", upPath); if (Error_Succeed != upError) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Try to clean Upgraded Dir. But get Upgraded path error = %u.", upError); return FALSE; } int nDelSuc = 0, nDelFail = 0, nFileCount = 0; nFileCount = ProcessFileDelete(upPath.GetData(), nDelSuc, nDelFail, false); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Delete [Upgraded] result(%s): count(%d), suc(%d), failed(%d).", upPath.GetData(), nFileCount, nDelSuc, nDelFail); } //-------------------------------------------------------------------------------------------- //版本清理中默认进行dump清理 int closeDmpClear = 0; spConfig->ReadConfigValueInt("ResourceWatcher", "CloseDmpClear", closeDmpClear); if (!closeDmpClear) { //执行删除流程rvc/dmp CSimpleStringA dmpPath; ErrorCodeEnum dmpError = pFunc->GetPath("Temp", dmpPath); if (Error_Succeed != dmpError) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Try to clean Dump Dir. But get Temp path error = %u.", dmpError); return FALSE; } #ifdef RVC_OS_LINUX dmpPath = dmpPath + SPLIT_SLASH_STR + ".." + SPLIT_SLASH_STR + "dmp"; // +"/../dmp" #else dmpPath = dmpPath + CSimpleStringA::Format("\\..\\dmp"); #endif // RVC_OS_LINUX int nDelSuc = 0, nDelFail = 0, nFileCount = 0; nFileCount = ProcessFileDelete(dmpPath.GetData(), nDelSuc, nDelFail, false); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Delete [Dump] result(%s): count(%d), suc(%d), failed(%d).", dmpPath.GetData(), nFileCount, nDelSuc, nDelFail); } //-------------------------------------------------------------------------------------------- //清理ver文件夹 int closeVerClear = 0; spConfig->ReadConfigValueInt("ResourceWatcher", "CloseVerClear", closeVerClear); if (!closeVerClear) { int verSaved = DEFAULT_VERSION_SAVED_COUNT; int tmpSaved = 0; vector intallInfoVects; vector files; spConfig->ReadConfigValueInt("ResourceWatcher", "VerSaveCnt", tmpSaved); if (tmpSaved > DEFAULT_VERSION_SAVED_COUNT) { verSaved = tmpSaved; } //获取当前目录下的文件夹名称, 将符合命名规则的终端版本名称push_back CSimpleStringA csPath, verPath; ErrorCodeEnum Error = m_pEntity->GetFunction()->GetPath("RootVer", csPath); //获取当前版本路劲 例如:C:\Run if (Error_Succeed == Error) { if (csPath.IsNullOrEmpty()) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("get currVer path is null"); return FALSE; } else { verPath = csPath; //csPath在后面被用了,还需要个存储version路径变量 DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("CUR VERSION PATH = %s.", csPath.GetData()); } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get Ver path error = %u.", Error); return FALSE; } //判断哪些是版本文件夹 #ifdef RVC_OS_LINUX DIR* dp; struct dirent* dirp; //过滤非目标版本文件夹 if ((dp = opendir(csPath.GetData())) != NULL) { while ((dirp = readdir(dp)) != NULL) { //files.push_back(string(dirp->d_name)); CInstallInfo verInfo = {}; DWORD dwMajor(0), dwMinor(0), dwRevision(0), dwBuild(0); int n = sscanf(dirp->d_name, "%d.%d.%d.%d", &dwMajor, &dwMinor, &dwRevision, &dwBuild); if (n != 4) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Not version file.[%s]", dirp->d_name); continue; } else { CVersion verName(dwMajor, dwMinor, dwRevision, dwBuild); if (verName.IsValid() && verName < info.InstallVersion) //对高于自身版本的文件不予删除 { intallInfoVects.push_back(verName); } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Not version file.[%s]", dirp->d_name); } } } closedir(dp); } #else long hFile = 0; struct _finddata_t fileinfo;//文件信息读取结构 string p; if ((hFile = _findfirst(p.assign(string(csPath.GetData())).append("\\*").c_str(), &fileinfo)) != -1) { do { CInstallInfo verInfo = {}; DWORD dwMajor(0), dwMinor(0), dwRevision(0), dwBuild(0); int n = sscanf(fileinfo.name, "%d.%d.%d.%d", &dwMajor, &dwMinor, &dwRevision, &dwBuild); if (n != 4) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Not version file.[%s]", fileinfo.name); continue; } else { CVersion verName(dwMajor, dwMinor, dwRevision, dwBuild); if (verName.IsValid() && verName < info.InstallVersion) { intallInfoVects.push_back(verName); } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Not version file.[%s]", fileinfo.name); } } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } #endif // RVC_OS_LINUX int nPackCount = intallInfoVects.size(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Install Package's count: %d", nPackCount); bool bFailFlag = false; int nDelVersionCnt = 0; std::string tInfo(""); //执行版本删除流程 if (nPackCount != 0) { int nSavedCount = 0; sort(intallInfoVects.begin(), intallInfoVects.end()); vector::reverse_iterator riter = intallInfoVects.rbegin(); while (riter != intallInfoVects.rend()) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("InstallPackage Info: %s", (LPCTSTR)(*riter).ToString()); if (++nSavedCount <= verSaved) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Save above version"); riter++; continue; } CSimpleStringA tVerPath; int nDelSuc = 0, nDelFail = 0, nFileCount = 0; #ifdef RVC_OS_LINUX tVerPath = verPath + SPLIT_SLASH_STR + (*riter).ToString(); #else tVerPath = verPath + "\\" + (*riter).ToString(); #endif // RVC_OS_LINUX nFileCount = ProcessFileDelete(tVerPath.GetData(), nDelSuc, nDelFail, true); //版本文件夹连目录一起清理 DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Delete Version result(%s): count(%d), suc(%d), failed(%d).", tVerPath.GetData(), nFileCount, nDelSuc, nDelFail); if (nDelFail) { bFailFlag = true; } else { nDelVersionCnt++; tInfo = tInfo + "|" + std::string((*riter).ToString().GetData()); } riter++; } } nLstFailed = bFailFlag ? 1 : 0; spConfigRun->WriteConfigValueHexInt("VersionClear", "OptVer", info.InstallVersion.GetVersion64()); spConfigRun->WriteConfigValueInt("VersionClear", "DelVerCnt", nDelCount + nDelVersionCnt); spConfigRun->WriteConfigValueInt("VersionClear", "LastCondi", nLstFailed); spConfigRun->WriteConfigValue("VersionClear", "LastTime", (LPCTSTR)CSimpleStringA::Format("0x%08X", (DWORD)CSmallDateTime::GetNow())); if (nDelVersionCnt > 0) { std::string warn = "Delete Vesion file count : " + std::to_string((long long)nDelVersionCnt) + ". ----- " + tInfo + "."; LogWarn(Severity_Low, Error_Debug, LOG_WARN_VER_DELETE, CSimpleStringA::Format("%s", warn.c_str())); } } return TRUE; } void ResourceWatcherFSM::DeleteVideoFiles() { int backDays = 0, closeVideoClear = 0; CSmartPointer pFunc = GetEntityBase()->GetFunction(); CSmartPointer spConfig; pFunc->OpenConfig(Config_CenterSetting, spConfig); spConfig->ReadConfigValueInt("ResourceWatcher", "CloseVideoClear", closeVideoClear); if (closeVideoClear) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("CenterSetting no need video clear."); return; } spConfig->ReadConfigValueInt("ResourceWatcher", "VideoBackDays", backDays); if (backDays <= 0) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("video default backdays:30 days."); backDays = VIDEO_DEFAULT_BACKDAYS; } CSimpleStringA videoPath, verPath; ErrorCodeEnum Error = m_pEntity->GetFunction()->GetPath("LocalVideo", videoPath); //获取Video路径 if (Error_Succeed == Error) { if (videoPath.IsNullOrEmpty()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get LocalVideo path NULL"); return; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("VIDEO PATH = %s.", videoPath.GetData()); } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("get LocalVideo error. error = %u.", Error); return; } int nDelSuc = 0, nDelFail = 0, nFileCount = 0; nFileCount = ProcessFileDelete(videoPath.GetData(), nDelSuc, nDelFail, false, backDays); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Delete [Video] result(%s): count(%d), suc(%d), failed(%d).", videoPath.GetData(), nFileCount, nDelSuc, nDelFail); } void ResourceWatcherFSM::SelfTest(EntityTestEnum eTestType, CSmartPointer pTransactionContext) { if (Test_ShakeHand == eTestType) { pTransactionContext->SendAnswer(Error_Succeed); } } void ResourceWatcherFSM::HardwareInfoTimer(void* pData) { if (hardwareCheckFlag > 0) { GetSystemCPUStatus(); GetSystemMemoryStatus(); } GetEntityBase()->GetFunction()->ResetTimer(TIMER_HARDWARE_CHECK, hardwareCheckTime); } void ResourceWatcherFSM::DiskCheckTimer(void* pData) { if (diskCheckFlag > 0) { GetSystemDiskStatus(); } GetEntityBase()->GetFunction()->ResetTimer(TIMER_DISK_CHECK, diskCheckTime); } ErrorCodeEnum ResourceWatcherFSM::CheckNetType( SpReqAnsContext::Pointer ctx) { ErrorCodeEnum ec = Error_Succeed; int netType = 0; //默认未知 #ifdef RVC_OS_LINUX int i = 0; int sockfd; struct ifconf ifconf; struct ifreq* ifreq; char buf[1024]; //初始化ifconf ifconf.ifc_len = 1024; ifconf.ifc_buf = buf; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("socket error"); } //获取所有接口信息 ioctl(sockfd, SIOCGIFCONF, &ifconf); //逐个获取Ip地址 int size = ifconf.ifc_len / sizeof(struct ifreq); ifreq = (struct ifreq*)buf; string netName(ifreq->ifr_name); if (size == 1 && netName == "lo") //只有逻辑地址 -- 网线被拔出 { netType = 1; } else { for (i = size; i > 0; i--) { string netName(ifreq->ifr_name); //有其他网卡 -- 有线 if (netName != "lo") { netType = 2; } ifreq++; } } #else CoInitialize(NULL); // 通过NLA接口获取网络状态 IUnknown* pUnknown = NULL; bool bOnline = true;//是否在线 HRESULT Result = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, IID_IUnknown, (void**)&pUnknown); if (SUCCEEDED(Result)) { INetworkListManager* pNetworkListManager = NULL; if (pUnknown) Result = pUnknown->QueryInterface(IID_INetworkListManager, (void **)&pNetworkListManager); if (SUCCEEDED(Result)) { VARIANT_BOOL IsConnect = VARIANT_FALSE; if (pNetworkListManager) { //Result = pNetworkListManager->get_IsConnectedToInternet(&IsConnect); //检测互联网连接 Result = pNetworkListManager->get_IsConnected(&IsConnect); //检测本地网络 } if (SUCCEEDED(Result)) { bOnline = (IsConnect == VARIANT_TRUE) ? true : false; } } if (pNetworkListManager) pNetworkListManager->Release(); } if (pUnknown) pUnknown->Release(); if (bOnline == true) { netType = 2; } else { netType = 1; } #endif // RVC_OS_LINUX if (ctx != NULL) { ctx->Ans.netType = netType; ctx->Answer(ec); } return ec; } ErrorCodeEnum ResourceWatcherFSM::GetBizLinks( SpReqAnsContext::Pointer ctx) { LOG_FUNCTION(); ErrorCodeEnum ec = Error_Succeed; int filter = ctx->Req.filter; //后续过滤使用 CAutoArray bizLinks; CAutoArray bizNames; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); if (filter == 0) //用户管理桌面业务网址 { CSimpleStringA mLink(""), adLink(""), tLink(""); spCtSettingConfig->ReadConfigValue("Chromium", "UserMgrUrlFulture", mLink); if (mLink.GetLength() != 0) { CSimpleStringA tName = CSimpleStringA("主站点"); bizNames.Append(&tName, 0, 1); bizLinks.Append(&mLink, 0, 1); } spCtSettingConfig->ReadConfigValue("Chromium", "UserMgrAd", adLink); if (adLink.GetLength() != 0) { CSimpleStringA tName = CSimpleStringA("广告站点"); bizNames.Append(&tName, 0, 1); bizLinks.Append(&adLink, 0, 1); } int bizCnt = 0; CSimpleStringA info(""), getLink(""); do {// 主站点|www.test.com bizCnt++; CSimpleStringA chineseName(""); CSimpleStringA url(""); getLink = CSimpleStringA("DesktopDetectUrl").Append(std::to_string(bizCnt).c_str()); spCtSettingConfig->ReadConfigValue("ResourceWatcher", getLink.GetData(), info); if (info.GetLength() != 0) { CAutoArray arr = info.Split('|'); int len = arr.GetCount(); if (len != 2) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[%s]Not Detect Url", info.GetData()); } else { chineseName = arr[0]; url = arr[1]; bizNames.Append(&chineseName, 0, 1); bizLinks.Append(&url, 0, 1); } } } while (info.GetLength() != 0); } else if (filter == 1) //错误页集中配置、准入网址 { int bizCnt = 0; CSimpleStringA info(""), getLink(""); do {// 准入服务|AccessAuth|accessUrl bizCnt++; CSimpleStringA chineseName(""), entityName(""), key(""); CSimpleStringA url(""); getLink = CSimpleStringA("ErrPageDetectUrl").Append(std::to_string(bizCnt).c_str()); spCtSettingConfig->ReadConfigValue("ResourceWatcher", (LPCTSTR)getLink, info); if (info.GetLength() != 0) { CAutoArray arr = info.Split('|'); int len = arr.GetCount(); if (len != 3) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[%s]Not errPage Check config info.", info.GetData()); } else { chineseName = arr[0]; entityName = arr[1]; key = arr[2]; spCtSettingConfig->ReadConfigValue(entityName.GetData(), key.GetData(), url); if (url.GetLength() != 0) { bizNames.Append(&chineseName, 0, 1); bizLinks.Append(&url, 0, 1); } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Get errPage detecet url failed. EntityName:(%s), Key:(%s).", entityName.GetData(), key.GetData()); } } } } while (info.GetLength() != 0); } ctx->Ans.bizLinks = bizLinks; ctx->Ans.bizNames = bizNames; if (ctx != NULL) { ctx->Answer(ec); } return ec; } #ifdef _MSC_VER bool ResourceWatcherFSM::CreateLinkFile(const CSimpleStringA& szStartAppPath, const CSimpleStringA& szAddCmdLine, const CSimpleStringA& szDestLnkPath, const CSimpleStringA& szIconPath) { HRESULT hr = CoInitialize(NULL); bool bRet = false; if (SUCCEEDED(hr)) { IShellLink* pShellLink; hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pShellLink); if (SUCCEEDED(hr)) { pShellLink->SetPath(szStartAppPath); string strTmp = szStartAppPath; int nStart = strTmp.find_last_of("/\\"); pShellLink->SetWorkingDirectory(strTmp.substr(0, nStart).c_str()); pShellLink->SetArguments(szAddCmdLine); if (szIconPath) { pShellLink->SetIconLocation(szIconPath, 0); } IPersistFile* pPersistFile; hr = pShellLink->QueryInterface(IID_IPersistFile, (void**)&pPersistFile); if (SUCCEEDED(hr)) { hr = pPersistFile->Save(CSimpleStringA2W(szDestLnkPath).GetData(), FALSE); if (SUCCEEDED(hr)) { bRet = true; } pPersistFile->Release(); } pShellLink->Release(); } CoUninitialize(); } return bRet; } void ResourceWatcherFSM::CreateLink(const CSimpleStringA& exePath, const CSimpleStringA& csVersion) { LPITEMIDLIST lp; SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &lp); CHAR lstr[100] = ""; SHGetPathFromIDList(lp, lstr); CSimpleStringA s = lstr; s += "\\可视柜台.lnk"; CSimpleStringA icoPath; ErrorCodeEnum Error = GetEntityBase()->GetFunction()->GetPath("RootVer", icoPath); icoPath = icoPath + "\\" + csVersion.GetData() + "\\bin\\VTM.ico"; if (!CreateLinkFile(exePath, "", s, icoPath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CreateLinkFile DESKTOP fail"); } SHGetSpecialFolderLocation(0, CSIDL_PROGRAMS, &lp); memset(lstr, 0, strlen(lstr)); SHGetPathFromIDList(lp, lstr); s = lstr; s += "\\可视柜台.lnk"; if (!CreateLinkFile(exePath, "", s, icoPath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CreateLinkFile CSIDL_PROGRAMS fail"); } } bool ResourceWatcherFSM::CopyExeToRoot(const CSimpleStringA& csVersion) { CSimpleStringA rootVerPath, exePath; ErrorCodeEnum rc = GetEntityBase()->GetFunction()->GetPath("RootVer", rootVerPath); exePath = rootVerPath + "\\VTM.exe"; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("exePath:%s", exePath.GetData()); if (rc == Error_Succeed) { CSimpleStringA srcExePath, csPath = rootVerPath; srcExePath = rootVerPath + "\\" + csVersion.GetData() + "\\bin\\VTM.exe"; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("srcExePath:%s exePath:%s", srcExePath.GetData(), exePath.GetData()); if (!ExistsFileA(srcExePath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("%s is not exist!", srcExePath.GetData()); return false; } if (!CopyFileA(srcExePath.GetData(), exePath.GetData(), FALSE)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("CopyFileA Fail error :%d ", GetLastError()); return false; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetPath 4 RootVer failed: %s", SpStrError(rc)); return false; } return true; } bool ResourceWatcherFSM::GetVtmVersionFromActiveTxt(CSimpleStringA& csVersion) { bool bRet = false; CSimpleStringA rootVerPath; ErrorCodeEnum rc = GetEntityBase()->GetFunction()->GetPath("RootVer", rootVerPath);//获取version根路径 if (rc != Error_Succeed) { LogWarn(Severity_Middle, Error_Exception, LOG_RESOURCEWATCHER_OPEN_ACTIVE_FAIL, "testActive fail , get RootVer path is failed"); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A06")("testActive fail , get RootVer path is failed!"); return false; } CSimpleStringA strActiveFile = CSimpleStringA::Format("%s\\active.txt", rootVerPath.GetData()); FILE* pFile = fopen(strActiveFile.GetData(), "rb+"); if (pFile != NULL) { char szTemp[256] = {}; char szVersion[32] = {}; int n = fread(szTemp, 1, 256, pFile); strncpy_s(szVersion, sizeof(szVersion), szTemp, _TRUNCATE); csVersion = szVersion; fclose(pFile); bRet = true; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Open active.txt failed."); bRet = false; } return bRet; } bool ResourceWatcherFSM::GetRegValue(HKEY hKey, LPCTSTR lpcszParam, CHAR* pSzValue, DWORD* pDwSizeOfSz) { DWORD dwType = REG_SZ; TCHAR szValue[MAX_PATH + 1] = { 0 }; DWORD dwSize = MAX_PATH * sizeof(CHAR); LONG lResult = RegQueryValueEx(hKey, lpcszParam, NULL, &dwType, (LPBYTE)szValue, pDwSizeOfSz); if (lResult == ERROR_SUCCESS) { strcpy_s(pSzValue, *pDwSizeOfSz, szValue); return true; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("RegQueryValueEx for \"%s\" error, result=%ld.", lpcszParam, lResult); return false; } } void ResourceWatcherFSM::DetectAutoStartupCover() { const int nStartupType = DetectAutoStartupType(); ErrorCodeEnum rc = Error_InvalidState; const int setType = InitialAutoStartupSetType(); bool toCheckAndDelteAutostartFile(false); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("current startup type:%d, aim start type:%d", nStartupType, setType); switch (setType) { case 1://将VBS改成EXE,前提是VBS必须已在注册表 if (nStartupType == 1) { rc = ChangeAutoStartupWithExe(); } break; case 2: //设置使用EXE注册表自启动 if (nStartupType == 1 || nStartupType == 0 || nStartupType == 3) { rc = ChangeAutoStartupWithExe(); if (rc == Error_Succeed && nStartupType == 3) { toCheckAndDelteAutostartFile = true; } } break; case 5: //设置使用EXE注册表自启动(涵盖所有类型) if (nStartupType == 1 || nStartupType == 0 || nStartupType == 3 || nStartupType == 4) { rc = ChangeAutoStartupWithExe(); if (rc == Error_Succeed && (nStartupType == 3 || nStartupType == 4)) { toCheckAndDelteAutostartFile = true; } } break; case 3: //不设置开机自启动 if (nStartupType == 1 || nStartupType == 2) { rc = ChangeAutoStartupWithExe(false, true); } else if (nStartupType == 3 || nStartupType == 4) { toCheckAndDelteAutostartFile = true; } break; case 4: //恢复VBS启动(防止EXE启动失败) if (nStartupType == 2 || nStartupType == 0) { rc = ChangeAutoStartupWithExe(true); } break; default: break; } if (toCheckAndDelteAutostartFile) { CSimpleStringA strLnkPath(true); bool scriptTypeOrNot; if (IsHasSetAutoStartupByFolder(strLnkPath, scriptTypeOrNot) && !strLnkPath.IsNullOrEmpty()) { BOOL rmRet = RemoveFileA(strLnkPath); if (!rmRet && ExistsFileA(strLnkPath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("remove auto start lnk file failed: %s, GLE=%u", strLnkPath.GetData(), GetLastError()); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("remove auto start lnk file: %s", strLnkPath.GetData()); } } } } static int Is32R64Platform() { static int isWow64 = -1; typedef BOOL(WINAPI* LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); if (isWow64 == -1) { BOOL bIsWow64 = FALSE; LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process"); if (NULL != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("detect is running with 64bit or not failed: %u", GetLastError()); return -1; } else { isWow64 = bIsWow64 ? 1 : 0; } } } return isWow64; } int ResourceWatcherFSM::DetectAutoStartupType() { LOG_FUNCTION(); int vbsType = -1; DWORD dwFlag = KEY_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS; if (Is32R64Platform() != 0) { dwFlag |= KEY_WOW64_64KEY; } bool explorerSet = false; CSimpleStringA regeditValue(true); HKEY hKey; LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), 0, dwFlag, &hKey); if (lResult == ERROR_SUCCESS) { DWORD dwType = REG_SZ; DWORD dwSize = MAX_PATH * sizeof(TCHAR); TCHAR szValue[MAX_PATH + 1] = { 0 }; memset(szValue, '\0', MAX_PATH + 1); lResult = RegQueryValueEx(hKey, "Shell", NULL, &dwType, (LPBYTE)szValue, &dwSize); if (lResult == ERROR_SUCCESS) { std::string strValue(szValue); regeditValue = szValue; strValue = SP::Utility::ToLower(strValue); CSimpleStringA value(strValue.c_str()); if (value.IsStartWith("wscript", true) && value.IsEndWith(".vbs", true)) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_AUTO_STARTUP_FROM_REGIST, value); vbsType = 1; } else if (value.IsEndWith("vtm.exe", true)) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_CHECK_AUTO_STARTUP_WITH_EXE, value); vbsType = 2; } else if (value.Compare("explorer.exe") == 0) { vbsType = 0; explorerSet = true; } else { LogWarn(Severity_Low, Error_Debug, LOG_WARN_CHECK_AUTO_STARTUP_UNKNOWN, value); vbsType = 0; } } else { LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_CHECK_AUTO_STARTUP_FROM_REGIST_FAILED, CSimpleStringA::Format("RegQueryValueEx error returned %u, GLE=%u.", lResult, GetLastError())); } } else { LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_CHECK_AUTO_STARTUP_FROM_REGIST_FAILED, CSimpleStringA::Format("RegOpenKeyEx error, GLE=%u.", GetLastError())); } RegCloseKey(hKey); if (vbsType == 0 || vbsType == -1) { CSimpleStringA strLnkPath(true); bool scriptType = false; if (IsHasSetAutoStartupByFolder(strLnkPath, scriptType)) { if (!scriptType) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_CHECK_AUTO_STARTUP_WITH_STARTMENU_FROMSETUP, strLnkPath); vbsType = 3; } else { LogWarn(Severity_Low, Error_Debug, LOG_WARN_CHECK_AUTO_STARTUP_WITH_STARTMENU_FROMSCRIPT, strLnkPath); vbsType = 4; } } else if (vbsType == 0 && explorerSet) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_NOT_AUTO_STARTUP_FROM_REGIST, regeditValue); } } return vbsType; } ErrorCodeEnum ResourceWatcherFSM::ChangeAutoStartupWithExe(bool resetVBS, bool resetExplorer) { const char* exploreExe = "explorer.exe"; ErrorCodeEnum result(Error_Succeed); CSimpleStringA exePath(true); if (resetExplorer) { exePath = exploreExe; } else { result = GetEntityBase()->GetFunction()->GetPath("RootVer", exePath); if (exePath.IsNullOrEmpty() || result != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A09").setAPI("ChangeAutoStartupWithExe")("Get RootVer path failed: %d", result); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_UPDATE_AUTO_STARTUP_WITH_EXE_FAILED, CSimpleStringA::Format("Get RootVer path failed: %d", result)); return Error_Unexpect; } if (!resetVBS) exePath.Append("\\VTM.exe"); else exePath.Append("\\spexplorerfast.vbs"); if (!ExistsFileA(exePath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A09").setAPI("ChangeAutoStartupWithExe")("[%s] is not existed!", exePath.GetData()); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_UPDATE_AUTO_STARTUP_WITH_EXE_FAILED, CSimpleStringA::Format("[%s] is not existed!", exePath.GetData())); return Error_NotExist; } } DWORD dwFlag = KEY_WRITE; if (Is32R64Platform() != 0) { dwFlag |= KEY_WOW64_64KEY; } HKEY hKey; LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), 0, dwFlag, &hKey); if (lResult == ERROR_SUCCESS) { lResult = RegSetValueExA(hKey, "Shell", 0, REG_SZ, (const BYTE*)exePath.GetData(), exePath.GetLength()); if (lResult == ERROR_SUCCESS) { LogWarn(Severity_Low, Error_Debug, LOG_WARN_UPDATE_AUTO_STARTUP_WITH_EXE_SUCC , CSimpleStringA::Format("RegSetValueExA for Shell with %s succ!", exePath.GetData())); result = Error_Succeed; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A09").setAPI("ChangeAutoStartupWithExe") ("RegSetValueExA for Shell with %s failed: %d", exePath.GetData(), lResult); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_UPDATE_AUTO_STARTUP_WITH_EXE_FAILED , CSimpleStringA::Format("RegSetValueExA for Shell with %s failed: %d", exePath.GetData(), lResult)); result = Error_Unexpect; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A09").setAPI("ChangeAutoStartupWithExe") ("RegOpenKeyEx for write %s failed: %d", exePath.GetData(), lResult); LogWarn(Severity_Middle, Error_Unexpect, LOG_WARN_UPDATE_AUTO_STARTUP_WITH_EXE_FAILED , CSimpleStringA::Format("RegOpenKeyEx for write %s failed: %d", exePath.GetData(), lResult)); result = Error_Unexpect; } RegCloseKey(hKey); return result; } int ResourceWatcherFSM::InitialAutoStartupSetType() { int ret = 0; CSmartPointer spConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spConfig); int value(0); spConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "AutoStartCMD", value); if (value != 0) { ret = value; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Get AutoStartCMD from CS: %d", ret); } return ret; } BOOL ResourceWatcherFSM::IsHasSetAutoStartupByFolder(CSimpleStringA& strPath, bool& scriptsType) { BOOL result(FALSE); strPath.Clear(); scriptsType = false; const char* STARTUP_DIR_FULL_PATH = "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp"; const char* STRATUP_FILENAME_FROM_SCRIPTS = "spexplorerauto.lnk"; #ifdef DEVOPS_ON_ST /*DevOps流水线编译,ST环境*/ const char* CMB_LINK_FILE_NAME = "招商银行可视柜台(ST测试).lnk"; #elif defined(DEVOPS_ON_UAT)/*DevOps流水线编译,UAT环境*/ const char* CMB_LINK_FILE_NAME = "招商银行可视柜台(UAT测试).lnk"; #elif defined(DEVOPS_ON_PRD)/*DevOps流水线编译,PRD环境*/ const char* CMB_LINK_FILE_NAME = "招商银行可视柜台.lnk"; #elif defined(DEVOPS_ON_DEV)/*DevOps流水线编译,Dev环境*/ const char* CMB_LINK_FILE_NAME = "招商银行可视柜台(开发).lnk"; #else/*本地编译等非DevOps环境编译的版本*/ const char* CMB_LINK_FILE_NAME = "招商银行可视柜台.lnk"; #endif if (!ExistsDirA(STARTUP_DIR_FULL_PATH)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("[%s] dir is not exist!", STARTUP_DIR_FULL_PATH); return result; } strPath = STARTUP_DIR_FULL_PATH; strPath += "\\"; strPath += CMB_LINK_FILE_NAME; if (ExistsFileA(strPath)) { result = TRUE; } else { auto arr = fileutil_get_sub_files(STARTUP_DIR_FULL_PATH); if (arr != NULL) { for (int i = 0; i < arr->nelts; ++i) { char* file = ARRAY_IDX(arr, i, char*); char* filename = strrchr(file, '\\'); if (filename != NULL) { filename += 1; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("autostartup[%s]", filename); if (filename != NULL/* && strcmp(filename, CMB_LINK_FILE_NAME) == 0*/) { CSimpleStringA strfilename(filename); if (strfilename.IsStartWith("招商银行可视柜台") && strfilename.IsEndWith(".lnk")) { strPath = file; result = TRUE; break; } } } toolkit_array_free2(arr); } } if (!result) { CSimpleStringA fullStartFileNameFromScripts(STARTUP_DIR_FULL_PATH); fullStartFileNameFromScripts += "\\"; fullStartFileNameFromScripts += STRATUP_FILENAME_FROM_SCRIPTS; if (ExistsFileA(fullStartFileNameFromScripts)) { strPath = fullStartFileNameFromScripts; scriptsType = true; result = TRUE; } else { // Get and display the user name. const DWORD INFO_BUFFER_SIZE = 2048; char infoBuf[INFO_BUFFER_SIZE]; ZeroMemory(infoBuf, INFO_BUFFER_SIZE); DWORD bufCharCount = INFO_BUFFER_SIZE; if (!GetUserName(infoBuf, &bufCharCount)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetUserName failed, GLE=%u", GetLastError()); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("User name:%s", infoBuf); fullStartFileNameFromScripts = CSimpleStringA::Format("C:\\Users\\%s\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup", infoBuf); fullStartFileNameFromScripts += "\\"; fullStartFileNameFromScripts += STRATUP_FILENAME_FROM_SCRIPTS; if (ExistsFileA(fullStartFileNameFromScripts)) { scriptsType = true; strPath = fullStartFileNameFromScripts; result = TRUE; } } } } return result; } void ResourceWatcherFSM::DetectVersionHasChangedAndWarn() { CSmartPointer spRunConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spRunConfig); UINT64 utVersion = 0; spRunConfig->ReadConfigValueHexInt("VersionMonitor", "LastVer", utVersion); CVersion lastVer(utVersion); if (lastVer.IsValid() && lastVer > m_RvcSysinfo.InstallVersion) { CSimpleStringA rootVerPath; CSimpleStringA warnInfo = CSimpleStringA::Format("version changed from %s to %s", lastVer.ToString().GetData(), m_RvcSysinfo.InstallVersion.ToString().GetData()); GetEntityBase()->GetFunction()->GetPath("RootVer", rootVerPath); CSimpleStringA csPath = rootVerPath + SPLIT_SLASH_STR + "active.txt"; if (!ExistsFileA(csPath)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A0A").setAPI(__FUNCTION__) ("%s: active.txt not exist!", warnInfo.GetData()); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_ACTIVE_FILE_CHANGE, CSimpleStringA::Format("%s: active.txt not exist!", warnInfo.GetData())); } else { CSimpleFileComponent activeFileInfo; HANDLE hFile = CreateFileA( csPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (hFile == INVALID_HANDLE_VALUE) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A0A").setAPI(__FUNCTION__) ("%s: active.txt open failed %u", warnInfo.GetData(), GetLastError()); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_ACTIVE_FILE_CHANGE, CSimpleStringA::Format("%s: active.txt open failed %u", warnInfo.GetData(), GetLastError())); } else { GetFileTime(hFile, (LPFILETIME)&activeFileInfo.mftCreate, (LPFILETIME)&activeFileInfo.mftAccess, (LPFILETIME)&activeFileInfo.mftModified); CloseHandle(hFile); char szFormat1[128] = { 0 }; GetTimeFormatStr(szFormat1, 128, (FILETIME*)&activeFileInfo.mftCreate); char szFormat2[128] = { 0 }; GetTimeFormatStr(szFormat2, 128, (FILETIME*)&activeFileInfo.mftAccess); char szFormat3[128] = { 0 }; GetTimeFormatStr(szFormat3, 128, (FILETIME*)&activeFileInfo.mftModified); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A0A").setAPI(__FUNCTION__) ("%s: active.txt create at %s, access at %s, modified at %s", warnInfo.GetData(), szFormat1, szFormat2, szFormat3); LogWarn(Severity_Middle, Error_Debug, LOG_WARN_ACTIVE_FILE_CHANGE, CSimpleStringA::Format( "%s: active.txt create at %s, access at %s, modified at %s", warnInfo.GetData(), szFormat1, szFormat2, szFormat3)); } } } if (!lastVer.IsValid() || lastVer != m_RvcSysinfo.InstallVersion) { spRunConfig->WriteConfigValueHexInt("VersionMonitor", "LastVer", m_RvcSysinfo.InstallVersion.GetVersion64()); } } void ResourceWatcherFSM::DetectDestopFileAndWarn(bool bClear, CSimpleStringA& strFileSaveList) { const DWORD INFO_BUFFER_SIZE = 2048; char infoBuf[INFO_BUFFER_SIZE]; DWORD bufCharCount = INFO_BUFFER_SIZE; char sys_disk = '\0'; bufCharCount = INFO_BUFFER_SIZE; if (!GetComputerName(infoBuf, &bufCharCount)) DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetComputerName failed, GLE=%u", GetLastError()); else DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Computer name: %s", infoBuf); // Get and display the user name. ZeroMemory(infoBuf, INFO_BUFFER_SIZE); bufCharCount = INFO_BUFFER_SIZE; if (!GetUserName(infoBuf, &bufCharCount)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetUserName failed, GLE=%u", GetLastError()); } else { CSimpleStringA filelist(true); int dirCount(0), fileCount(0); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("User name: %s", infoBuf); CSimpleStringA desktopFullPath = CSimpleStringA::Format("C:\\Users\\%s\\Desktop", infoBuf); CSimpleStringA desktopPublicPath("C:\\Users\\Public\\Desktop"); CAutoArray desktopPaths; desktopPaths.Init(2); desktopPaths[0] = desktopFullPath; desktopPaths[1] = desktopPublicPath; for (int k = 0; k < desktopPaths.GetCount(); ++k) { CSimpleStringA& curPath = desktopPaths[k]; auto arr = fileutil_get_sub_files(curPath); if (arr != NULL) { for (int i = 0; i < arr->nelts; ++i) { char* file = ARRAY_IDX(arr, i, char*); char* filename = strrchr(file, '\\'); if (filename != NULL) { filename += 1; } else { filename = file; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("filename:%s", filename); bool toRecord = true; if (bClear) { std::string strLowFileName = SP::Utility::ToLower(std::string(filename)); if (strFileSaveList.IsNullOrEmpty() || strFileSaveList.IndexOf(strLowFileName.c_str()) == -1) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("delete desktop file:%s", filename); RemoveFileA(file); if (!ExistsFileA(file)) { toRecord = false; } } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("skip to delete: %s", filename); } } if (toRecord) { fileCount++; if (!filelist.IsNullOrEmpty()) { filelist += "|"; } filelist += filename; } } if (arr->nelts > 0) { filelist += ";"; } toolkit_array_free2(arr); } arr = fileutil_get_sub_dirs(curPath); if (arr != NULL) { for (int i = 0; i < arr->nelts; ++i) { char* dir = ARRAY_IDX(arr, i, char*); char* dirname = strrchr(dir, '\\'); if (dirname != NULL) { dirname += 1; } else { dirname = dir; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("dir name:%s", dirname); bool toRecord = true; if (bClear) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("remove desktop dir:%s", dirname); RemoveDirRecursiveA(dir); if (!ExistsDirA(dir)) { toRecord = false; } } if (toRecord) { dirCount++; if (!filelist.IsNullOrEmpty() && i != 0) { filelist += "|"; } filelist += dirname; } } if (arr->nelts > 0) { filelist += ";"; } toolkit_array_free2(arr); } } LogWarn(Severity_Low, Error_Debug, LOG_INFO_DESKTOP_FILESTATUS ,CSimpleStringA::Format("{\"subject\":\"desktop_file\",\"clear_flag\":\"%d\",\"username\":\"%s\",\"file_count\":%d,\"dir_count\":%d,\"content\":\"%s\"}" , bClear ? 1 : 0, infoBuf, fileCount, dirCount, filelist.GetLength() < 950 ? filelist.GetData() : (filelist.SubString(0, 950) + "....").GetData())); } } ErrorCodeEnum ResourceWatcherFSM::DetectVTMInstalledBySetup(BOOL& fYes) { HKEY key; ErrorCodeEnum result(Error_Succeed); fYes = FALSE; CSimpleStringA regPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{123BBC1D-8555-4E90-96CA-70E678FF5C24}_is1"; LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_ALL_ACCESS, &key); if (ERROR_SUCCESS == lResult) { fYes = TRUE; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Found {123BBC1D-8555-4E90-96CA-70E678FF5C24}"); LogWarn(Severity_Low, Error_Debug, LOG_INFO_INSTALL_BY_SETUP, "Intalled by Setup"); } else if (ERROR_FILE_NOT_FOUND == lResult) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Not Found {123BBC1D-8555-4E90-96CA-70E678FF5C24}"); fYes = FALSE; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("RegOpenKeyEx For{123BBC1D-8555-4E90-96CA-70E678FF5C24} error, Result=%ld.", lResult); fYes = FALSE; result = Error_Unexpect; } RegCloseKey(key); return result; } bool ResourceWatcherFSM::RegRdVtmVersion(CSimpleStringA& VTMpath, CSimpleStringA& vtmVersion) { bool bRet = false; HKEY key; CSimpleStringA regPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\VTM"; CSimpleStringA regParaPath = "path"; CSimpleStringA regParaVersion = "version"; LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_ALL_ACCESS, &key); char arrVTMpath[MAX_PATH] = { 0 }, arrVTMversion[MAX_PATH] = { 0 }; if (ERROR_SUCCESS == lResult) { DWORD dwValue = MAX_PATH * sizeof(CHAR); bool res1 = GetRegValue(key, regParaPath, arrVTMpath, &dwValue); if (res1) { bRet = true; VTMpath = arrVTMpath; } else { bRet = false; RegCloseKey(key); return bRet; } dwValue = MAX_PATH * sizeof(CHAR); bool res2 = GetRegValue(key, regParaVersion, arrVTMversion, &dwValue); if (res2) { bRet = true; vtmVersion = arrVTMversion; } else { bRet = false; RegCloseKey(key); return bRet; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("%s::RegOpenKeyEx error, Result=%ld.", __FUNCTION__, lResult); bRet = false; } RegCloseKey(key); return bRet; } bool ResourceWatcherFSM::RegWtVtmPath() { bool bRet = true; HKEY key; CSimpleStringA regPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_ALL_ACCESS, &key)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Open Reg failed."); bRet = false; } DWORD dwDisposition; regPath += "\\VTM"; if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE, regPath.GetData(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisposition)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Create key failed"); bRet = false; } if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath.GetData(), 0, KEY_ALL_ACCESS, &key)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Set value failed"); bRet = false; } CSimpleStringA para = "path"; CSimpleStringA exePath; ErrorCodeEnum Error = GetEntityBase()->GetFunction()->GetPath("RootVer", exePath); if (Error_Succeed == Error) { exePath += "\\VTM.exe"; if (ERROR_SUCCESS != RegSetValueEx(key, para.GetData(), 0, REG_SZ, (BYTE*)exePath.GetData(), MAX_PATH)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Set path value failed"); bRet = false; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Get path of VTM.exe failed."); } ::RegCloseKey(key); return bRet; } bool ResourceWatcherFSM::RegWtVtmVersion() { bool bRet = true; HKEY key; CSimpleStringA regPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths"; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath, 0, KEY_ALL_ACCESS, &key)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Open Reg failed."); bRet = false; } DWORD dwDisposition; regPath += "\\VTM"; if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE, regPath.GetData(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dwDisposition)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Create key failed"); bRet = false; } if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPath.GetData(), 0, KEY_ALL_ACCESS, &key)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Set value failed"); bRet = false; } CSimpleStringA para = "version"; CSimpleStringA csVersion; if (GetVtmVersionFromActiveTxt(csVersion)) { //RegSetValueEx(key, para.GetData(), 0, REG_SZ, (BYTE*)csVersion.GetData(), MAX_PATH); if (ERROR_SUCCESS != RegSetValueEx(key, para.GetData(), 0, REG_SZ, (BYTE*)csVersion.GetData(), MAX_PATH)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Set value failed"); bRet = false; } } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Get version of VTM.exe failed."); } ::RegCloseKey(key); return bRet; } bool ResourceWatcherFSM::RegOperation() { bool bRet = true; CSimpleStringA csVersion, VtmRegPath, VtmRegVersion; bool bGetActive = GetVtmVersionFromActiveTxt(csVersion); bool bRegRead = RegRdVtmVersion(VtmRegPath, VtmRegVersion); CSimpleStringA rootVerPath, exePath; ErrorCodeEnum rc = GetEntityBase()->GetFunction()->GetPath("RootVer", rootVerPath); exePath = rootVerPath + "\\VTM.exe"; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("csVersion :%s ,VtmRegVersion:%s ", csVersion.GetData(), VtmRegVersion.GetData()); if (!ExistsFileA(exePath) || !bGetActive || !bRegRead || (0 != VtmRegVersion.Compare(csVersion, true))) { if (!ExistsFileA(exePath) && !CopyExeToRoot(csVersion)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Copy VTM.exe to version root fail."); bRet = false; } else { if (!RegWtVtmPath()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("RegWtVtmPath failed."); } if (!RegWtVtmVersion()) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("RegWtVtmVersion failed."); } CreateLink(exePath, csVersion); } } return bRet; } bool ResourceWatcherFSM::UpdateExe() { int updateExe = 0; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); spCtSettingConfig->ReadConfigValueInt("NonExclusive", "UpdateExe", updateExe); if (updateExe == 1) return true; return false; } void ResourceWatcherFSM::VerifySignature() { LOG_FUNCTION(); CSimpleStringA strMsg(true); char* buffer = new char[MAX_PATH]; getcwd(buffer, MAX_PATH); strcat(buffer, "\\*"); DWORD elapsed = 0; DWORD dwStart = GetTickCount(); DWORD dwEnd = GetTickCount(); VerifySignature(buffer); if (m_nonSignedFiles.size() > 0) { CSimpleStringA fileList = ""; for (size_t i = 0; i < m_nonSignedFiles.size(); i++) { fileList += GetFileName(m_nonSignedFiles[i]); if (i < m_nonSignedFiles.size() - 1) fileList += ","; } int toDisplay = m_iNonSignedTotal < m_iNonSignedDisplay ? m_iNonSignedTotal : m_iNonSignedDisplay; strMsg = CSimpleStringA::Format("共有%d个文件未签名,其中%d个为:%s.", m_iNonSignedTotal, toDisplay, fileList.GetData()); } dwEnd = GetTickCount(); elapsed = dwEnd - dwStart; strMsg = strMsg + CSimpleStringA::Format("签名耗时:%dms", elapsed); LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_FILE_NOT_TRUSTED, (LPCTSTR)strMsg); delete buffer; } void ResourceWatcherFSM::VerifySignature(const CSimpleStringA& filePath) { HANDLE hFind = NULL; WIN32_FIND_DATA fileInfo; DWORD64 dwSize = 0; hFind = FindFirstFile(filePath, &fileInfo); if (hFind == INVALID_HANDLE_VALUE) return; string strDirPath = filePath; do { if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!strcmp(fileInfo.cFileName, ".") || !strcmp(fileInfo.cFileName, "..")) { //Do nothing for "." and ".." folders } else { strDirPath.insert(strDirPath.find("*"), string(fileInfo.cFileName) + "\\"); VerifySignature(strDirPath.c_str()); strDirPath = filePath; } } else { CSimpleStringA fileName = fileInfo.cFileName; string strFileName = fileName; string strFilePath; if(strFileName.empty() || (strFileName.rfind(".dll") != strFileName.length() - 4 && strFileName.rfind(".exe") != strFileName.length() - 4)) continue; strFilePath = strDirPath; strFilePath.replace(strFilePath.find("*"), strFilePath.length(), string(fileInfo.cFileName)); if (!RetrieveDigitalSignatureInfo(strFilePath.c_str())) { if (m_iNonSignedTotal < m_iNonSignedDisplay) { m_nonSignedFiles.push_back(strFilePath.c_str()); } m_iNonSignedTotal++; } } } while (FindNextFile(hFind, &fileInfo)); FindClose(hFind); } void ResourceWatcherFSM::DetectAndClearDesktopFile() { #if defined(RVC_OS_WIN) CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); int clearDesktopFlag(0); CSimpleStringA strFileWhiteSheet(true); spCtSettingConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "ClearDesktopSwitch", clearDesktopFlag); if (!!clearDesktopFlag) { spCtSettingConfig->ReadConfigValue(GetEntityBase()->GetEntityName(), "DesktopWhiteSheet", strFileWhiteSheet); if (!strFileWhiteSheet.IsNullOrEmpty()) { std::string strLowFileName = SP::Utility::ToLower(std::string(strFileWhiteSheet.GetData())); strFileWhiteSheet = strLowFileName.c_str(); } } DetectDestopFileAndWarn(!!clearDesktopFlag, strFileWhiteSheet); #endif //RVC_OS_WIN } CSimpleStringA ResourceWatcherFSM::GetFileName(const CSimpleStringA& filePath) { CSimpleStringA tmp = filePath; auto arrPath = tmp.Split('\\'); int size = arrPath.GetCount(); return arrPath[size - 1]; } bool ResourceWatcherFSM::RetrieveDigitalSignatureInfo(const char* pFilePath) { HCERTSTORE hStore = NULL; HCRYPTMSG hMsg = NULL; WCHAR* wpFilePath = NULL; int len = ::MultiByteToWideChar(CP_ACP, 0, pFilePath, -1, NULL, 0); if (len > 0) { wpFilePath = new wchar_t[len + 1]; std::memset(wpFilePath, 0, (len + 1) * sizeof(wchar_t)); ::MultiByteToWideChar(CP_ACP, 0, pFilePath, -1, &wpFilePath[0], len); } if (CryptQueryObject(CERT_QUERY_OBJECT_FILE, wpFilePath, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, &hStore, &hMsg, NULL)) { DWORD dwCountSigners = 0; DWORD dwcbSz = sizeof(dwCountSigners); if (CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwCountSigners, &dwcbSz)) { if (dwCountSigners != 0) { dwcbSz = 0; CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwcbSz); if (dwcbSz) { PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwcbSz]; if (pSignerInfo) { DWORD dwcbSz2 = dwcbSz; if (CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, pSignerInfo, &dwcbSz) && dwcbSz == dwcbSz2) { if (VerifyFirstCertificate(hStore, pSignerInfo) || VerifyOtherCertificate(pSignerInfo)) return true; } delete[] pSignerInfo; pSignerInfo = NULL; } } } } } if (hStore != NULL) { CertCloseStore(hStore, 0); hStore = NULL; } if (hMsg != NULL) { CryptMsgClose(hMsg); hMsg = NULL; } return false; } bool ResourceWatcherFSM::VerifyFirstCertificate(HCERTSTORE hStore, PCMSG_SIGNER_INFO pSignerInfo) { CERT_INFO ci = { 0 }; ci.Issuer = pSignerInfo->Issuer; ci.SerialNumber = pSignerInfo->SerialNumber; PCCERT_CONTEXT pCertContext = NULL; int c = 0; bool ret = false; for (;; c++) { pCertContext = CertFindCertificateInStore(hStore, ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&ci, pCertContext); if (!pCertContext) { break; } DWORD dwcbSz; char* pBuff; dwcbSz = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); if (dwcbSz != 0) { pBuff = new (std::nothrow) char[dwcbSz]; if (pBuff) { if (CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pBuff, dwcbSz) == dwcbSz) { if (!strcmp(pBuff, "China Merchants Bank Co., Ltd") || !strcmp(pBuff, "Microsoft Corporation")) ret = true; } delete[] pBuff; pBuff = NULL; } } } if (pCertContext) { CertFreeCertificateContext(pCertContext); pCertContext = NULL; } return ret; } bool ResourceWatcherFSM::VerifyOtherCertificate(PCMSG_SIGNER_INFO pSignerInfo) { int ret = false; for (DWORD a = 0; a < pSignerInfo->UnauthAttrs.cAttr; a++) { #ifndef szOID_NESTED_SIGNATURE #define szOID_NESTED_SIGNATURE "1.3.6.1.4.1.311.2.4.1" #endif if (pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId && lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[a].pszObjId, szOID_NESTED_SIGNATURE) == 0) { HCRYPTMSG hMsg = ::CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL); if (hMsg) { if (::CryptMsgUpdate(hMsg, pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData, pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData, TRUE)) { DWORD dwSignerInfo = 0; ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo); if (dwSignerInfo != 0) { PCMSG_SIGNER_INFO pSignerInfo2 = (PCMSG_SIGNER_INFO)new (std::nothrow) BYTE[dwSignerInfo]; if (pSignerInfo2) { if (::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo2, &dwSignerInfo)) { CRYPT_DATA_BLOB c7Data; c7Data.cbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->cbData; c7Data.pbData = pSignerInfo->UnauthAttrs.rgAttr[a].rgValue->pbData; //ret = FindAppropriateStoreAndVerifyFirstCertificate(pSignerInfo2, &c7Data); HCERTSTORE hStore = NULL; hStore = CertOpenStore(CERT_STORE_PROV_PKCS7, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, NULL, 0, &c7Data); ret = hStore && VerifyFirstCertificate(hStore, pSignerInfo2); if (hStore) { ::CertCloseStore(hStore, CERT_CLOSE_STORE_FORCE_FLAG); hStore = NULL; } } delete[] pSignerInfo2; pSignerInfo2 = NULL; } } } ::CryptMsgClose(hMsg); } } } return ret; } long long GetDirSizeFsm(string dirPath) { long long fileLen = 0; long hFile = 0; //文件信息 struct _finddata_t fileinfo; string p; if ((hFile = _findfirst(p.assign(dirPath).append("\\*").c_str(), &fileinfo)) != -1) { do { //如果是目录,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) fileLen += GetDirSizeFsm(p.assign(dirPath).append("\\").append(fileinfo.name)); } else { fileLen += fileinfo.size; } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } return fileLen; } struct CmpByValueFromBiggest //从最大的排起 { bool operator()(const pair& l, const pair& r) { return l.second > r.second; } }; //unordered_map fileSpace; unordered_map fileIncreasedSpace; vector> sortFileIncreasedSpace; unordered_map fileSpace; vector> sortFileSpace; static bool spaceLock = false; void ResourceWatcherFSM::CheckDiskFileSpace() { if (spaceLock) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("当前已有硬盘扫描进行中,跳过。"); return; } else { spaceLock = true; //加锁 } CSmartPointer spConfigRun; CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spConfigRun); GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); int lastDiskUsed = 0; unsigned long long lastVer = 0; int spaceIncrease = 0; //硬盘增长阈值 spConfigRun->ReadConfigValueHexInt("SpaceInfo", "OptVer", lastVer); spConfigRun->ReadConfigValueInt("SpaceInfo", "DiskTotalUsed(GB)", lastDiskUsed); spCtSettingConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "DiskUsedIncreaseInt(GB)", spaceIncrease); if (spaceIncrease == 0) { spaceIncrease = 5; //默认阈值5GB } if (!m_bNeedForceDiskCheck) //是否需要强制全盘扫描 - 硬盘使用过高是会强制 { if (lastVer == m_RvcSysinfo.InstallVersion.GetVersion64()) { if (lastDiskUsed != 0 && ((int)(GetDiskUsedByte() / (1024 * 1024 * 1024)) - lastDiskUsed) < spaceIncrease) //增长值判定 { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("硬盘空间增长未超过阈值,无需扫描。"); if (spaceLock) { spaceLock = false; //释放锁 } return; } else { //降低磁盘扫描频率 SYSTEMTIME localTime; GetLocalTime(&localTime); if (m_diskLastWarnHour != localTime.wHour) { m_diskLastWarnHour = localTime.wHour; CSmartPointer spConfigRun; ErrorCodeEnum eErr = GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spConfigRun); if (eErr == Error_Succeed) { spConfigRun->WriteConfigValueInt("WarnRecord", "disk", m_diskLastWarnHour); } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("硬盘增长超过阈值,重点目录扫描!"); } else { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("磁盘增长最近1小时已扫描一次,暂不扫描。"); if (spaceLock) { spaceLock = false; //释放锁 } return; } } } else { spConfigRun->WriteConfigValueHexInt("SpaceInfo", "OptVer", m_RvcSysinfo.InstallVersion.GetVersion64()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("新版本,重点目录扫描"); } } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("强制扫描。"); } string path = "D:"; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("扫描D盘。"); long long fileLen = 0; long hFile = 0; //文件信息 struct _finddata_t fileinfo; string p; if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) { do { //如果是目录,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) fileLen = GetDirSizeFsm(p.assign(path).append("\\").append(fileinfo.name)); else { continue; } } else { fileLen = fileinfo.size; } CSimpleStringA resLen = CSimpleStringA::Format("%lld B", fileLen); if (fileLen >= 1024 && fileLen < (1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / 1024; resLen = CSimpleStringA::Format("%.2f KB", len); } else if (fileLen >= (1024 * 1024) && fileLen < (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024); resLen = CSimpleStringA::Format("%.2f MB", len); } else if (fileLen >= (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024 * 1024); resLen = CSimpleStringA::Format("%.2f GB", len); } CSimpleStringA oldLenStr(""); long oldLen = 0; spConfigRun->ReadConfigValue("SpaceInfo", p.assign(path).append("\\").append(fileinfo.name).c_str(), oldLenStr); oldLen = atol(oldLenStr.GetData()); fileIncreasedSpace[p.assign(path).append("\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)) - oldLen; //保存在unordered_map中 fileSpace[p.assign(path).append("\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("[%s] 大小为 [%s]", p.assign(path).append("\\").append(fileinfo.name).c_str(), resLen.GetData()); if (lastVer != m_RvcSysinfo.InstallVersion.GetVersion64()) { spConfigRun->WriteConfigValue("SpaceInfo", p.assign(path).append("\\").append(fileinfo.name).c_str(), CSimpleStringA::Format("%ld MB", (long)(fileLen / (1024 * 1024)))); } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } //获取version目录下的文件夹大小 CSimpleStringA csPath; ErrorCodeEnum Error = m_pEntity->GetFunction()->GetPath("RootVer", csPath); //获取当前版本路劲 例如:C:\Run fileLen = 0; hFile = 0; p = ""; if ((hFile = _findfirst(p.assign(csPath.GetData()).append("\\*").c_str(), &fileinfo)) != -1) { do { //如果是目录,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) fileLen = GetDirSizeFsm(p.assign(csPath.GetData()).append("\\").append(fileinfo.name)); else { continue; } } else { fileLen = fileinfo.size; } CSimpleStringA resLen = CSimpleStringA::Format("%lld B", fileLen); if (fileLen >= 1024 && fileLen < (1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / 1024; resLen = CSimpleStringA::Format("%.2f KB", len); } else if (fileLen >= (1024 * 1024) && fileLen < (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024); resLen = CSimpleStringA::Format("%.2f MB", len); } else if (fileLen >= (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024 * 1024); resLen = CSimpleStringA::Format("%.2f GB", len); } CSimpleStringA oldLenStr(""); //MB long oldLen = 0; spConfigRun->ReadConfigValue("SpaceInfo", p.assign(csPath.GetData()).append("\\").append(fileinfo.name).c_str(), oldLenStr); oldLen = atol(oldLenStr.GetData()); fileIncreasedSpace[p.assign(csPath.GetData()).append("\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)) - oldLen; //保存在unordered_map中 fileSpace[p.assign(csPath.GetData()).append("\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("[%s] 大小为 [%s]", p.assign(csPath.GetData()).append("\\").append(fileinfo.name).c_str(), resLen.GetData()); if (lastVer != m_RvcSysinfo.InstallVersion.GetVersion64()) { spConfigRun->WriteConfigValue("SpaceInfo", p.assign(csPath.GetData()).append("\\").append(fileinfo.name).c_str(), CSimpleStringA::Format("%ld MB", (long)(fileLen / (1024 * 1024)))); } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } //获取rvc目录下的文件夹大小 fileLen = 0; hFile = 0; p = ""; if ((hFile = _findfirst(p.assign(path).append("\\rvc\\*").c_str(), &fileinfo)) != -1) { do { //如果是目录,迭代之 //如果不是,加入列表 if ((fileinfo.attrib & _A_SUBDIR)) { if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) fileLen = GetDirSizeFsm(p.assign(path).append("\\rvc\\").append(fileinfo.name)); else { continue; } } else { fileLen = fileinfo.size; } CSimpleStringA resLen = CSimpleStringA::Format("%lld B", fileLen); if (fileLen >= 1024 && fileLen < (1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / 1024; resLen = CSimpleStringA::Format("%.2f KB", len); } else if (fileLen >= (1024 * 1024) && fileLen < (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024); resLen = CSimpleStringA::Format("%.2f MB", len); } else if (fileLen >= (1024 * 1024 * 1024)) { DOUBLE len = (DOUBLE)fileLen / (1024 * 1024 * 1024); resLen = CSimpleStringA::Format("%.2f GB", len); } CSimpleStringA oldLenStr(""); long oldLen = 0; spConfigRun->ReadConfigValue("SpaceInfo", p.assign(path).append("\\rvc\\").append(fileinfo.name).c_str(), oldLenStr); oldLen = atol(oldLenStr.GetData()); fileIncreasedSpace[p.assign(path).append("\\rvc\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)) - oldLen; //保存在unordered_map中 fileSpace[p.assign(path).append("\\rvc\\").append(fileinfo.name)] = (long)(fileLen / (1024 * 1024)); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("[%s] 大小为 [%s]", p.assign(path).append("\\rvc\\").append(fileinfo.name).c_str(), resLen.GetData()); if (lastVer != m_RvcSysinfo.InstallVersion.GetVersion64()) { spConfigRun->WriteConfigValue("SpaceInfo", p.assign(path).append("\\rvc\\").append(fileinfo.name).c_str(), CSimpleStringA::Format("%ld MB", (long)(fileLen / (1024 * 1024)))); } } while (_findnext(hFile, &fileinfo) == 0); _findclose(hFile); } if (lastVer != m_RvcSysinfo.InstallVersion.GetVersion64()) { //写入硬盘量 spConfigRun->WriteConfigValueInt("SpaceInfo", "DiskTotalUsed(GB)", GetDiskUsedByte() / (1024 * 1024 * 1024)); if (spaceLock) { spaceLock = false; //释放锁 } return; //新版本无需上报文件信息,更新完运行时文件后即可结束 } //获取增量最大的前十文件夹信息 sortFileIncreasedSpace = vector>(fileIncreasedSpace.begin(), fileIncreasedSpace.end()); sort(sortFileIncreasedSpace.begin(), sortFileIncreasedSpace.end(), CmpByValueFromBiggest()); int topFileNum = sortFileIncreasedSpace.size(); if (topFileNum > 10) { topFileNum = 10; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("变化最大的%d个文件夹信息。", topFileNum); fileLen = 0; for (int i = 0; i < topFileNum; i++) { fileLen = sortFileIncreasedSpace[i].second; if (fileLen == 0) break; CSimpleStringA warn1 = CSimpleStringA::Format("TOP %d: [%s], 增量[%ld]MB", i + 1, sortFileIncreasedSpace[i].first.c_str(), sortFileIncreasedSpace[i].second); LogWarn(Severity_Low, Error_Resource, LOG_RESOURCEWATCHER_FILE_TOPINCREASED_SPACE, warn1.GetData()); } if (m_bNeedForceDiskCheck) { //获取空间占用最大前十文件夹信息 sortFileSpace = vector>(fileSpace.begin(), fileSpace.end()); sort(sortFileSpace.begin(), sortFileSpace.end(), CmpByValueFromBiggest()); int topFileSize = sortFileSpace.size(); if (topFileSize > 10) { topFileSize = 10; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("空间占用最大的%d个文件夹信息。", topFileSize); fileLen = 0; for (int i = 0; i < topFileSize; i++) { fileLen = sortFileSpace[i].second; if (fileLen == 0) break; CSimpleStringA warn2 = CSimpleStringA::Format("空间占用排名 %d: [%s], 大小[%ld]MB", i + 1, sortFileSpace[i].first.c_str(), sortFileSpace[i].second); LogWarn(Severity_Low, Error_Resource, LOG_RESOURCEWATCHER_FILE_TOPUSED_SPACE, warn2.GetData()); } m_bNeedForceDiskCheck = false; } if (spaceLock) { spaceLock = false; //释放锁 } } void ResourceWatcherFSM::GetSystemDiskStatus() { if (m_diskHighPercent <= 0) { m_diskHighPercent = 90; //默认硬盘告警百分比90% } ULARGE_INTEGER ulAvailFree, ulTotalBytes, ulTotalFree; BOOL ret = GetDiskFreeSpaceEx(NULL, &ulAvailFree, &ulTotalBytes, &ulTotalFree); if (ret == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetSystemDiskStatus.GetDiskFreeSpaceEx failed(%d).", GetLastError()); return; } CSimpleStringA csBinPath; ErrorCodeEnum Error = m_pEntity->GetFunction()->GetPath("Bin", csBinPath); //获取当前终端运行磁盘位置 DWORD dwAvFree = ulAvailFree.QuadPart / MILLION; DWORD dwTotal = ulTotalBytes.QuadPart / MILLION; DWORD dwTotalFree = ulTotalFree.QuadPart / MILLION; int ratio = dwTotalFree * 100 / dwTotal; if ((100 - ratio) > m_diskHighPercent) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("The disk has %d MB(%d%%) available.\n", dwTotalFree, ratio); string test(csBinPath.GetData()); char diskMessage[1024]; sprintf(diskMessage, "{\"Disk\":\"%c:\",\"total\":\"%0.2f GByte\",\"free ratio\":\"%d%%\"}", csBinPath.GetData()[0], (double)dwTotal / 1024, ratio); //oilyang@20200526 根据wq建议,降低磁盘空间偏少的告警频率 //SYSTEMTIME localTime; //GetLocalTime(&localTime); //if (m_diskLastWarnHour != localTime.wHour) //需要告警时才强制全盘扫描 //{ // m_diskLastWarnHour = localTime.wHour; // CSmartPointer spConfigRun; // ErrorCodeEnum eErr = GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spConfigRun); // if (eErr == Error_Succeed) { // spConfigRun->WriteConfigValueInt("WarnRecord", "disk", m_diskLastWarnHour); // } // //LogWarn(Severity_Low, Error_Resource, LOG_EVT_SELFCHECK_HARDDISK_TOO_HIGH, "Harddisk free space is few."); // LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_HARDDISK_TOO_HIGH, diskMessage); // m_bNeedForceDiskCheck = true; //} LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_HARDDISK_TOO_HIGH, diskMessage); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A05").setAPI("DiskUsedCheck")(diskMessage); m_bNeedForceDiskCheck = true; } else { m_bNeedForceDiskCheck = false; } CheckDiskFileSpaceTask* task4 = new CheckDiskFileSpaceTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task4); } ULONGLONG ResourceWatcherFSM::GetDiskUsedByte() { ULARGE_INTEGER ulAvailFree, ulTotalBytes, ulTotalFree; BOOL ret = GetDiskFreeSpaceEx(NULL, &ulAvailFree, &ulTotalBytes, &ulTotalFree); if (ret == 0) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetSystemDiskStatus.GetDiskFreeSpaceEx failed(%d).", GetLastError()); return -1; } CSimpleStringA csBinPath; ErrorCodeEnum Error = m_pEntity->GetFunction()->GetPath("Bin", csBinPath); //获取当前终端运行磁盘位置 return ulTotalBytes.QuadPart - ulTotalFree.QuadPart; } __int64 Filetime2Int64(const FILETIME& ftime) { LARGE_INTEGER li; li.LowPart = ftime.dwLowDateTime; li.HighPart = ftime.dwHighDateTime; return li.QuadPart; } __int64 CompareFileTime2(const FILETIME& preTime, const FILETIME& nowTime) { return Filetime2Int64(nowTime) - Filetime2Int64(preTime); } unordered_map oldProcessTime; unordered_map newProcessTime; unordered_map processName; unordered_map processCpu; bool cmp(const pair& a, const pair& b) { return a.second > b.second; } void ResourceWatcherFSM::GetSystemCPUStatus() { oldProcessTime.clear(); newProcessTime.clear(); processName.clear(); processCpu.clear(); FILETIME preIdleTime; FILETIME preKernelTime; FILETIME preUserTime; FILETIME preProcCreateTime; FILETIME preProcExitTime; FILETIME preProcKernelTime; FILETIME preProcUserTime; GetSystemTimes(&preIdleTime, &preKernelTime, &preUserTime); PROCESSENTRY32 pe32Old; pe32Old.dwSize = sizeof(pe32Old); //获得系统进程快照的句柄 HANDLE hProcessSnapOld = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnapOld == INVALID_HANDLE_VALUE) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("CreateToolhelp32Snapshot error."); return; } //首先获得第一个进程 BOOL bProcessOld = Process32First(hProcessSnapOld, &pe32Old); //循环获得所有进程 while (bProcessOld) { //进程名和进程ID HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32Old.th32ProcessID); GetProcessTimes(hProcess, &preProcCreateTime, &preProcExitTime, &preProcKernelTime, &preProcUserTime); oldProcessTime[pe32Old.th32ProcessID] = Filetime2Int64(preProcKernelTime) + Filetime2Int64(preProcUserTime); bProcessOld = Process32Next(hProcessSnapOld, &pe32Old); } CloseHandle(hProcessSnapOld); // 等待一段时间 Sleep(100); // 100毫秒 ULONGLONG deltaTime = 100 * 1000000; // 100毫秒转换为纳秒 FILETIME idleTime; FILETIME kernelTime; FILETIME userTime; FILETIME ProcCreateTime; FILETIME ProcExitTime; FILETIME procKernelTime; FILETIME procUserTime; GetSystemTimes(&idleTime, &kernelTime, &userTime); PROCESSENTRY32 pe32New; pe32New.dwSize = sizeof(pe32New); //获得系统进程快照的句柄 HANDLE hProcessSnapNew = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnapNew == INVALID_HANDLE_VALUE) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("CreateToolhelp32Snapshot error."); return; } //首先获得第一个进程 BOOL bProcessNew = Process32First(hProcessSnapNew, &pe32New); //循环获得所有进程 while (bProcessNew) { //进程名和进程ID HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pe32New.th32ProcessID); GetProcessTimes(hProcess, &ProcCreateTime, &ProcExitTime, &procKernelTime, &procUserTime); newProcessTime[pe32New.th32ProcessID] = Filetime2Int64(procKernelTime) + Filetime2Int64(procUserTime); processName[pe32New.th32ProcessID] = CSimpleStringA(pe32New.szExeFile); bProcessNew = Process32Next(hProcessSnapNew, &pe32New); } CloseHandle(hProcessSnapNew); auto idle = CompareFileTime2(preIdleTime, idleTime); auto kernel = CompareFileTime2(preKernelTime, kernelTime); auto user = CompareFileTime2(preUserTime, userTime); if (kernel + user == 0) return; CSystemRunInfo runInfo = { 0 }; GetEntityBase()->GetFunction()->GetSystemRunInfo(runInfo); for (int i = 0; i < runInfo.strRunningEntityNames.GetCount(); i++) //实体进程的名称默认全为sphost,需转换为对应实体名 { runInfo.strRunningEntityNames[i]; CEntityRunInfo entityInfo = { 0 }; GetEntityBase()->GetFunction()->GetEntityRunInfo(runInfo.strRunningEntityNames[i].GetData(), entityInfo); processName[entityInfo.dwProcessID] = runInfo.strRunningEntityNames[i]; } unordered_map::iterator it; for (it = newProcessTime.begin(); it != newProcessTime.end(); ++it) { int tPid = it->first; //进程的占用率 = 单位时间间隔里进程的CPU时间片占用 / 单位时间间隔里CPU的整体时间片 if (oldProcessTime.find(tPid) == oldProcessTime.end()) { continue; } // 转换为百分比 double tRatio = 100.0 * (newProcessTime[tPid] - oldProcessTime[tPid]) / deltaTime; if (tRatio > 0.0); { processCpu[tPid] = tRatio; } } vector> vec(processCpu.begin(), processCpu.end()); sort(vec.begin(), vec.end(), cmp); //根据CPU使用率从大到小进行排序 int len = min(10, vec.size()); CSimpleStringA procWarn = ""; for (int i = 0; i < len; ++i) //构建进程的CPU使用告警信息 { procWarn = procWarn + ",\"" + processName[vec[i].first] + "\":\"" + CSimpleStringA::Format("%.2f", vec[i].second) + "%\""; } double cpuRatio = 100.0 * (kernel + user - idle) / (kernel + user); if (m_cpuHighPercent <= 0) { m_cpuHighPercent = 80; //默认告警百分比80% } if (cpuWarnThreshold <= 0) { cpuWarnThreshold = 10; //默认满10次告一次警 } if (cpuRatio > (double)m_cpuHighPercent) { cpuWarnTime = cpuWarnTime % cpuWarnThreshold; if (cpuWarnTime == 0) //每达到一次阈值告警一次 { CSimpleStringA warn = CSimpleStringA::Format("{\"type\":\"cpu\", \"total_used\":\" %.2f", cpuRatio); warn = warn + "%\"" + procWarn + "}"; LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_CPU_TOO_HIGH, warn.GetData()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A03").setAPI("CpuUsedCheck")(warn.GetData()); if (cpuRatio > 98) //cpu极端异常情况 { LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_CPU_ERROR, warn.GetData()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A02")(warn.GetData()); } } cpuWarnTime++; } } unsigned long long convert_time_format(const FILETIME* ftime) { LARGE_INTEGER li; li.LowPart = ftime->dwLowDateTime; li.HighPart = ftime->dwHighDateTime; return li.QuadPart; } /// 时间转换 static uint64_t file_time_2_utc(const FILETIME* ftime) { LARGE_INTEGER li; li.LowPart = ftime->dwLowDateTime; li.HighPart = ftime->dwHighDateTime; return li.QuadPart; } /// 获得CPU的核数 static int get_processor_number() { SYSTEM_INFO info; GetSystemInfo(&info); return (int)info.dwNumberOfProcessors; } int ResourceWatcherFSM::GetCpuUsageRatio(int pid) { //cpu数量 static int processor_count_ = -1; //上一次的时间 static int64_t last_time_ = 0; static int64_t last_system_time_ = 0; FILETIME now; FILETIME creation_time; FILETIME exit_time; FILETIME kernel_time; FILETIME user_time; int64_t system_time; int64_t time; int64_t system_time_delta; int64_t time_delta; int cpu = -1; if (processor_count_ == -1) { processor_count_ = get_processor_number(); } GetSystemTimeAsFileTime(&now); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid); if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time)) { return -1; } system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time)) / processor_count_; time = file_time_2_utc(&now); if ((last_system_time_ == 0) || (last_time_ == 0)) { last_system_time_ = system_time; last_time_ = time; return -1; } system_time_delta = system_time - last_system_time_; time_delta = time - last_time_; if (time_delta == 0) return -1; cpu = (int)((system_time_delta * 100 + time_delta / 2) / time_delta); last_system_time_ = system_time; last_time_ = time; return cpu; } double GetMemoryUsageGB(int pid) { #ifdef WIN32 DWORDLONG mem = 0, vmem = 0; PROCESS_MEMORY_COUNTERS pmc; // get process hanlde by pid HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (GetProcessMemoryInfo(process, &pmc, sizeof(pmc))) { mem = pmc.WorkingSetSize; vmem = pmc.PagefileUsage; } CloseHandle(process); // use GetCurrentProcess() can get current process and no need to close handle // convert mem from B to GB double memGB = mem / (1024.0 * 1024.0 * 1024.0); return memGB; #else char file_name[64] = { 0 }; FILE* fd; char line_buff[512] = { 0 }; sprintf(file_name, "/proc/%d/status", pid); fd = fopen(file_name, "r"); if (nullptr == fd) return 0; char name[64]; int vmrss = 0; for (int i = 0; i < VMRSS_LINE - 1; i++) fgets(line_buff, sizeof(line_buff), fd); fgets(line_buff, sizeof(line_buff), fd); sscanf(line_buff, "%s %d", name, &vmrss); fclose(fd); // cnvert VmRSS from KB to MB return vmrss / 1024.0; #endif } unordered_map processMem; void ResourceWatcherFSM::GetSystemMemoryStatus() { MEMORYSTATUSEX statex; statex.dwLength = sizeof(statex); GlobalMemoryStatusEx(&statex); double totalMem = statex.ullTotalPhys / (1024.0 * 1024.0 * 1024.0); //GB unordered_map::iterator it; for (it = processName.begin(); it != processName.end(); ++it) { int tPid = it->first; double tmp = GetMemoryUsageGB(it->first); if (tmp > 0.0 && tmp < 100) { processMem[tPid] = 100 * (tmp / totalMem); } } //return; vector> vec(processMem.begin(), processMem.end()); sort(vec.begin(), vec.end(), cmp); //根据CPU使用率从大到小进行排序 int len = min(10, vec.size()); CSimpleStringA procWarn = ""; for (int i = 0; i < len; ++i) //构建进程的CPU使用告警信息 { procWarn = procWarn + ",\"" + processName[vec[i].first] + "\":\"" + CSimpleStringA::Format("%.1f", vec[i].second) + "%\""; } if (m_memHighPercent <= 0) { m_memHighPercent = 80; //默认告警百分比80% } if (memWarnThreshold <= 0) { memWarnThreshold = 10; //默认告警阈值10次 } if (statex.dwMemoryLoad > m_memHighPercent) { memWarnTime = memWarnTime % memWarnThreshold; if (memWarnTime == 0) //每达到阈值告警一次 { CSimpleStringA warn = CSimpleStringA::Format("{\"type\":\"mem\", \"total\":\"%.1f GByte\",\"total_used\":\" %d%%\"", totalMem, statex.dwMemoryLoad); warn = warn + procWarn + "}"; LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_MEMORY_TOO_HIGH, warn.GetData()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A04").setAPI("MemUsedCheck")(warn.GetData()); } memWarnTime++; } } int ResourceWatcherFSM::IsWifiConnected() { DWORD service_ver; HANDLE handle = NULL; int result = -1; DWORD err = WlanOpenHandle(WLAN_API_VERSION, NULL, &service_ver, &handle); if (err != 0) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("open wlan handle failed %d", err); return result; } PWLAN_INTERFACE_INFO_LIST info_list = NULL; PWLAN_INTERFACE_INFO interface_info = NULL; err = WlanEnumInterfaces(handle, NULL, &info_list); if (err != ERROR_SUCCESS) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("Enum wlan interface failed %d", err); WlanCloseHandle(handle, NULL); return -1; } const int count = info_list->dwNumberOfItems; for (int i = 0; i < count; ++i) { interface_info = &info_list->InterfaceInfo[i]; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("wireless interface name: %s", SP::Module::Util::W2S(interface_info->strInterfaceDescription).c_str()); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("state: %d", interface_info->isState); if (interface_info->isState == wlan_interface_state_connected) { result = 1; } DWORD radio_state_info_size = sizeof(WLAN_RADIO_STATE); PWLAN_RADIO_STATE radio_state_info_ptr = NULL; WLAN_OPCODE_VALUE_TYPE op_code = wlan_opcode_value_type_invalid; err = WlanQueryInterface(handle, &interface_info->InterfaceGuid, wlan_intf_opcode_radio_state, NULL, &radio_state_info_size, (PVOID*)&radio_state_info_ptr, &op_code); if (err != ERROR_SUCCESS) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM)("WlanQueryInterface failed %d", err); } else { const uint32_t count_of_phys = radio_state_info_ptr->dwNumberOfPhys; //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Number of valid PHYs: %d", count_of_phys); if (count_of_phys > 0 && result == -1) { if (dot11_radio_state_on == radio_state_info_ptr->PhyRadioState[0].dot11SoftwareRadioState) { result = 0; } else { /* for (int j = 0; j < count_of_phys; ++j) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("software radio state: %d, %d", j , radio_state_info_ptr->PhyRadioState[j].dot11SoftwareRadioState); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("hardware radio state: %d, %d", j, radio_state_info_ptr->PhyRadioState[j].dot11HardwareRadioState); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("**********************"); } */ } } } } if (info_list != NULL) { WlanFreeMemory(info_list); } WlanCloseHandle(handle, NULL); return result; } void ResourceWatcherFSM::DetectWallpaperAndWarn() { int vbsType = -1; DWORD dwFlag = KEY_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS; if (Is32R64Platform() != 0) { dwFlag |= KEY_WOW64_64KEY; } bool explorerSet = false; CSimpleStringA regeditValue(true); HKEY hKey; LONG lResult = RegOpenKeyEx(HKEY_CURRENT_USER,"Control Panel\\Desktop", 0, dwFlag, &hKey); if (lResult == ERROR_SUCCESS) { DWORD dwType = REG_SZ; DWORD dwSize = MAX_PATH * sizeof(TCHAR); TCHAR szValue[MAX_PATH + 1] = { 0 }; memset(szValue, '\0', MAX_PATH + 1); lResult = RegQueryValueEx(hKey, "Wallpaper", NULL, &dwType, (LPBYTE)szValue, &dwSize); if (lResult == ERROR_SUCCESS) { CSimpleStringA strMsg = CSimpleStringA::Format("{\"subject\":\"wallpaper_path\",\"value\":\"%s\"}", szValue); LogWarn(Severity_Low, Error_Debug, LOG_INFO_DESKTOP_WALLPAPER_PATH, strMsg); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("WallpaperSettings")(strMsg.GetData()); } else { CSimpleStringA strMsg = CSimpleStringA::Format("{\"subject\":\"wallpaper_path\",\"error\":\"RegQueryValueEx for Wallpaper returned %u, GLE=%u\"}", lResult, GetLastError()); LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_DESKTOP_WALLPAPER_PATH_FETCHFAILE, strMsg); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("WallpaperSettings").setResultCode("RTA5A0E")(strMsg.GetData()); } } else { CSimpleStringA strMsg = CSimpleStringA::Format("{\"subject\":\"wallpaper_path\",\"error\":\"RegOpenKeyEx for Desktop returned %u, GLE=%u\"}", lResult, GetLastError()); LogWarn(Severity_Low, Error_Unexpect, LOG_WARN_DESKTOP_WALLPAPER_PATH_FETCHFAILE, strMsg); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("WallpaperSettings").setResultCode("RTA5A0E")(strMsg.GetData()); } RegCloseKey(hKey); } #endif // _MSC_VER end硬件资源监控相关系统功能 CPU、内存、硬盘、网络wifi #ifdef RVC_OS_LINUX static bool spaceLock = false; void ResourceWatcherFSM::CheckDiskFileSpace() { if (spaceLock) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("当前已有硬盘扫描进行中,跳过。"); return; } else { spaceLock = true; //加锁 } //获取opt文件夹下的文件占用信息 FILE* fp = NULL; CSimpleStringA cmd = "du -h -s /opt/* | sort -rn | head"; if ((fp = popen(cmd.GetData(), "r")) == NULL) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("popen failed:%d", GetLastError()); return; } char buf[1024] = { 0 }; CSimpleStringA warnMsg(true); while (fgets(buf, sizeof(buf), fp)) { warnMsg = warnMsg + "|" + buf; } if (warnMsg.GetLength() > 0) { LogWarn(Severity_Low, Error_Resource, LOG_RESOURCEWATCHER_FILE_TOPUSED_SPACE, warnMsg.GetData()); //告警opt下的文件夹 } pclose(fp); //获取opt/rvc文件夹下的文件占用信息 FILE* fp2 = NULL; CSimpleStringA cmd2 = "du -h -s /opt/rvc/* | sort -rn | head"; if ((fp2 = popen(cmd2.GetData(), "r")) == NULL) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("popen failed:%d", GetLastError()); return; } CSimpleStringA warnMsg2(true); char buf2[1024] = { 0 }; while (fgets(buf2, sizeof(buf2), fp2)) { warnMsg2 = warnMsg2 + "|" + buf2; } if (warnMsg2.GetLength() > 0) { LogWarn(Severity_Low, Error_Resource, LOG_RESOURCEWATCHER_FILE_TOPUSED_SPACE, warnMsg2.GetData()); //告警opt/rvc下的文件夹 } pclose(fp2); if (spaceLock) { spaceLock = false; //释放锁 } } #endif // RVC_OS_LINUX ErrorCodeEnum ResourceWatcherFSM::CatchSystemBasicInfo(SystemBasicInfo& info) { #if defined(RVC_OS_WIN) ///**TODO(Gifur@10/10/2023): 待实现 */ return Error_NotImpl; #else CSimpleStringA runCfgPath; ErrorCodeEnum errCode = GetEntityBase()->GetFunction()->GetPath("RunCfg", runCfgPath); if (runCfgPath.IsNullOrEmpty()) return Error_Null; CSimpleStringA storeFilePath = runCfgPath + SPLIT_SLASH_STR + "SMBIOSData.txt"; if (!ExistsFileA(storeFilePath)) { RemoveFileA(storeFilePath); } std::string succStr, errStr; std::string runStr("dmidecode -t system > "); runStr += storeFilePath.GetData(); if (!SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("execute '%s' failed!", runStr.c_str()); if (!ExistsFileA(storeFilePath)) { RemoveFileA(storeFilePath); } return Error_Unexpect; } do { std::string succStr, errStr; std::string runStr("awk -F ':' '(NR>=7)&&(NR<=14)&&($0~\"Manufacturer\"){print$2}' "); runStr += storeFilePath.GetData(); if (SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { info.strManufacturer = SP::Utility::ToTrim(succStr).c_str(); } else { succStr = ""; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("fetch 'Manufacturer' failed!"); } } while (false); do { std::string succStr, errStr; std::string runStr("awk -F ':' '(NR>=7)&&(NR<=14)&&($0~\"Product Name\"){print$2}' "); runStr += storeFilePath.GetData(); if (SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { info.strProductName = SP::Utility::ToTrim(succStr).c_str(); } else { succStr = ""; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("fetch 'Product Name' failed!"); } } while (false); do { std::string succStr, errStr; std::string runStr("awk -F ':' '(NR>=7)&&(NR<=14)&&($0~\"Serial Number\"){print$2}' "); runStr += storeFilePath.GetData(); if (SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { info.strSerialNumber = SP::Utility::ToTrim(succStr).c_str(); } else { succStr = ""; DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("fetch 'Serial Number' failed!"); } } while (false); if (!ExistsFileA(storeFilePath)) { RemoveFileA(storeFilePath); } return Error_Succeed; #endif //RVC_OS_WIN } void ResourceWatcherFSM::AlarmSystemBasicInfo() { SystemBasicInfo info; if (Error_Succeed == CatchSystemBasicInfo(info)) { CSimpleStringA strResult("{"); if (!info.strManufacturer.IsNullOrEmpty()) { strResult += CSimpleStringA::Format("\"Manufacturer\":\"%s\"", info.strManufacturer.GetData()); } if (!info.strProductName.IsNullOrEmpty()) { if (strResult.GetLength() > 1) { strResult += ", "; } strResult += CSimpleStringA::Format("\"Product Name\":\"%s\"", info.strProductName.GetData()); } if (!info.strSerialNumber.IsNullOrEmpty()) { if (strResult.GetLength() > 1) { strResult += ", "; } strResult += CSimpleStringA::Format("\"Serial Number\":\"%s\"", info.strSerialNumber.GetData()); } strResult += "}"; LogWarn(Severity_Low, Error_Debug, LOG_INFO_DEVICE_SMBIOS_GET, strResult); } } BOOL ResourceWatcherFSM::DetectIsFirstRunAtBoot() { const BOOL bSet = SP::Module::Comm::IsFirsRunAppAfterSystemBoot(GetEntityBase(), LOG_RESOURCEWATCHER_FIRST_RUN_AFTER_BOOT); if (bSet) { ErrorCodeEnum eRet = GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_FRAMEWORK_FIRST_BOOT, SYSVAR_FRAMEWORK_FIRST_BOOT_YES); if (eRet != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("Set %s with %s failed: %d", SYSVAR_FRAMEWORK_FIRST_BOOT, SYSVAR_FRAMEWORK_FIRST_BOOT_YES, eRet); } } else { GetEntityBase()->GetFunction()->SetSysVar(SYSVAR_FRAMEWORK_FIRST_BOOT, SYSVAR_FRAMEWORK_FIRST_BOOT_NO); } return bSet; } #ifdef RVC_OS_LINUX void ResourceWatcherFSM::UploadMonitorSettings() { CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); int nSwitchOff(0); spCtSettingConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "MonitorListenOFF", nSwitchOff); if (!!nSwitchOff) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Cancel monitor change listen!"); if (m_bFirstRunAfterBoot) { CSimpleStringA value(true); bool res = GetMonitorInfo(value); LogWarn(Severity_Low, Error_Debug, LOG_INFO_MONITOR_SETTINGS, value); } } else { int nInterval(10000); int nValue(0); spCtSettingConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "MonitorListenInterval", nValue); if (nValue >= 10000) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Update monitor listen interval from %d to %d", nInterval, nValue); nInterval = nValue; } CSimpleStringA strLastMonitor(true); bool readFromCfgFalg(true); CSmartPointer spRunConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spRunConfig); spRunConfig->ReadConfigValue("MonitorAttribute", "LastInfo", strLastMonitor); do { CSimpleStringA value(true); bool res = GetMonitorInfo(value); if (!value.IsNullOrEmpty() && (strLastMonitor.IsNullOrEmpty() || (strLastMonitor.Compare(value) != 0))) { LogWarn(Severity_Low, Error_Debug, LOG_INFO_MONITOR_SETTINGS, value); CSmartPointer spRunConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Run, spRunConfig); spRunConfig->WriteConfigValue("MonitorAttribute", "LastInfo", value); strLastMonitor = value; if (readFromCfgFalg) { readFromCfgFalg = false; } } else if (readFromCfgFalg && !strLastMonitor.IsNullOrEmpty() && strLastMonitor.Compare(value) == 0) { LogWarn(Severity_Low, Error_Debug, LOG_INFO_MONITOR_SETTINGS, value); readFromCfgFalg = false; } Sleep(nInterval); } while (true); } } void ResourceWatcherFSM::DetectSoftwareInstallStatus() { CSmartPointer spCtSettingConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spCtSettingConfig); CSimpleStringA strSoftwaresNames[MAX_SOFTWARE_INSTALLED_DETECT_COUNT]; CSimpleStringA strSoftwaresVers[MAX_SOFTWARE_INSTALLED_DETECT_COUNT]; int nNameCounts = 0; for (int i = 0; i < MAX_SOFTWARE_INSTALLED_DETECT_COUNT; i++) { strSoftwaresNames[i] = ""; strSoftwaresVers[i] = ""; CSimpleStringA item = CSimpleStringA::Format("SoftwareInstallDetect%d", i); CSimpleStringA value(true); spCtSettingConfig->ReadConfigValue(GetEntityBase()->GetEntityName(), item, value); if (value.IsNullOrEmpty()) { break; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("CenterSettings:[%s]", value.GetData()); if (value.IndexOf("#") != -1) { /** CSimpleString会带Trim操作,在这里不适用 [Gifur@202485]*/ auto items = SP::Utility::Split(std::string(value.GetData()), '#'); strSoftwaresNames[i] = items[0].c_str(); strSoftwaresVers[i] = items[1].c_str(); } else { strSoftwaresNames[i] = value; } DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Detect SoftDetect from CentralSetting, %d: [%s],[%s],[%s]" , i, item.GetData(), strSoftwaresNames[i].GetData(), strSoftwaresVers[i].GetData()); nNameCounts++; } if (nNameCounts > 0) { for (int i = 0; i < nNameCounts; ++i) { CSimpleStringA runItem = CSimpleStringA::Format("dpkg -l | grep \"%s\" | awk '{print $3}'", strSoftwaresNames[i].GetData()); std::string additional(""); std::string succStr, errStr; std::string runStr(runItem.GetData()); if (SP::Module::Util::ShellExecute(runStr, succStr, errStr)) { if (succStr.empty()) { CSimpleStringA strMsg = CSimpleStringA::Format("{\"software_name\":\"%s\", \"version_status\":\"not installed\",\"detect_flag\":0}", strSoftwaresNames[i].GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_SOFTWARE_DETECT_NOT_EXISTS_BASE + i, strMsg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("SoftwareInstallStatus")(strMsg.GetData()); } else { succStr = SP::Utility::ToTrim(succStr); if (strSoftwaresVers[i].IsNullOrEmpty() || strSoftwaresVers[i].Compare(succStr.c_str()) == 0) { CSimpleStringA strMsg = CSimpleStringA::Format("{\"software_name\":\"%s\", \"version_status\":\"%s\",\"detect_flag\":1}" , strSoftwaresNames[i].GetData(), succStr.c_str(), strSoftwaresVers[i].GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_SOFTWARE_DETECT_EXISTS_BASE + i, strMsg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("SoftwareInstallStatus")(strMsg.GetData()); } else { CSimpleStringA strMsg = CSimpleStringA::Format("{\"software_name\":\"%s\", \"version_status\":\"%s\", \"expected\":\"%s\",\"detect_flag\":0}" , strSoftwaresNames[i].GetData(), succStr.c_str(), strSoftwaresVers[i].GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_SOFTWARE_DETECT_NOT_EXISTS_BASE + i, strMsg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("SoftwareInstallStatus")(strMsg.GetData()); } } } else { CSimpleStringA strMsg = CSimpleStringA::Format("{\"software_name\":\"%s\", \"version_status\":\"detect failed\", \"expected\":\"%s\",\"detect_flag\":0}" , strSoftwaresNames[i].GetData(), strSoftwaresVers[i].GetData()); LogWarn(Severity_Low, Error_Debug, LOG_WARN_SOFTWARE_DETECT_EXISTS_STATUS_FAILED, strMsg); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI("SoftwareInstallStatus").setResultCode("RTA5A0D")(strMsg.GetData()); } } } } UINT ResourceWatcherFSM::GetSystemDisplayVersion(CSimpleStringA& strVersion) { UINT result = 0; const char filePath[] = "/etc/os-version"; strVersion.Clear(); char tmp[33]; memset(tmp, 0, 33); inifile_read_str_s("Version", "MajorVersion", "unknown", tmp, 32, filePath); strVersion = tmp; strVersion += "."; memset(tmp, 0, 33); inifile_read_str_s("Version", "MinorVersion", "unknown", tmp, 32, filePath); strVersion += tmp; strVersion += "."; result = atoi(tmp); memset(tmp, 0, 33); inifile_read_str_s("Version", "OsBuild", "unknown", tmp, 32, filePath); strVersion += tmp; return result; } void ResourceWatcherFSM::UploadSysVersionInfo(UINT& ver) { std::map srcData; CSimpleStringA osver; ver = GetSystemDisplayVersion(osver); srcData.insert(std::make_pair("os-version", osver)); ////当前操作系统版本(系统信息) tk_utsname_t t; osutil_uname(&t); srcData.insert(std::make_pair("sysname", t.sysname)); ////当前操作系统名 srcData.insert(std::make_pair("release", t.release)); ////当前发布级别 srcData.insert(std::make_pair("version", t.version)); ////当前发布版本 srcData.insert(std::make_pair("machine", t.machine)); ////当前硬件体系类型 do { std::string sucContent, failedContent; std::string cmd("cat /proc/cpuinfo |grep \"model name\" | awk 'NR==1'"); bool ret = SP::Module::Util::ShellExecute(cmd, sucContent, failedContent); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("{%s}:{%s}{%s}", cmd.c_str(), sucContent.c_str(), failedContent.c_str()); auto elems = SP::Utility::Split(sucContent, ':'); if (elems.size() > 1) { sucContent = SP::Utility::ToTrim(elems[1]); } srcData.insert(std::make_pair("cpu-type", sucContent)); } while (false); auto ret = generateJsonStr(srcData); LogWarn(Severity_Low, Error_Hardware, LOG_RESOURCEWATCHER_SYSTEMINFO, ret.second.c_str()); } string ResourceWatcherFSM::MemoryProcessStatus() { CSmartPointer spFunction = this->GetEntityBase()->GetFunction(); ErrorCodeEnum erroCode = Error_Unexpect; int memTop = 10; //10个进程 map nameProcess; CSystemRunInfo runInfo = { 0 }; GetEntityBase()->GetFunction()->GetSystemRunInfo(runInfo); for (int i = 0; i < runInfo.strRunningEntityNames.GetCount(); i++) { string entityName = runInfo.strRunningEntityNames[i].GetData(); CEntityRunInfo entityInfo = { 0 }; GetEntityBase()->GetFunction()->GetEntityRunInfo(entityName.c_str(), entityInfo); nameProcess[to_string(entityInfo.dwProcessID)] = entityName; } FILE* fp; char buffer[2048]; string cmd = "ps c -eo pid,%mem,rss,command | sort -k3 -rn | head -" + to_string(memTop); fp = popen(cmd.c_str(), "r"); int i = 0; string s; string str[4]; //mem DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("MEM TOP %d PROCESS!", memTop); string topMessage = ""; while (i < memTop) { fgets(buffer, sizeof(buffer), fp); s = buffer; istringstream is(s); is >> str[0] >> str[1] >> str[2] >> str[3]; double temp; stringstream ss1; ss1 << str[2]; ss1 >> temp; temp = temp / (1024 * 1024); stringstream ss2; ss2 << std::setiosflags(std::ios::fixed) << std::setprecision(2) << temp; str[2] = ss2.str(); if (nameProcess.find(str[0]) != nameProcess.end()) { str[3] = nameProcess[str[0]]; } topMessage = topMessage + "\"" + str[3] + "\"" + ":" + "\"" + str[1] + "%\""; if (i != memTop - 1) { topMessage += ","; } ++i; } topMessage += "}"; pclose(fp); return topMessage; } long ResourceWatcherFSM::GetCPURunTime(CPUInfo* cpu) //获取CPU的当前信息,同时返回CPU使用时间 { FILE* fd; char buff[1024] = { 0 }; CPUInfo* cpuInfo = cpu; fd = fopen("/proc/stat", "r"); if (!fd) { //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Read CPU Info FAILED!"); return -1; } fgets(buff, sizeof(buff), fd); char name[64] = { 0 }; sscanf(buff, "%s %u %u %u %u %u %u %u", cpuInfo->name, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system, &cpuInfo->idle, &cpuInfo->lowait, &cpuInfo->irq, &cpuInfo->softirq); fclose(fd); return (cpuInfo->user + cpuInfo->nice + cpuInfo->system + cpuInfo->idle + cpuInfo->lowait + cpuInfo->irq + cpuInfo->softirq); } long ResourceWatcherFSM::ReadProcCPURunTime(DWORD pid, ProcCPUInfo* pInfo) { //根据pid读取进程占用的CPU时间 char file_name[64] = { 0 }; FILE* fd; char line_buff[1024] = { 0 }; sprintf(file_name, "/proc/%d/stat", pid); fd = fopen(file_name, "r"); if (nullptr == fd) { //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Read PROCESS[%d] CPU Info FAILED!", pid); return -1; } fgets(line_buff, sizeof(line_buff), fd); sscanf(line_buff, "%u %s", &pInfo->pid, pInfo->pname); const char* q = GetItems(line_buff, PROCESS_ITEM); sscanf(q, "%ld %ld %ld %ld", &pInfo->utime, &pInfo->stime, &pInfo->cutime, &pInfo->cstime); fclose(fd); return (pInfo->utime + pInfo->stime + pInfo->cutime + pInfo->cstime); } //获取第N项开始的指针 const char* ResourceWatcherFSM::GetItems(const char* buffer, unsigned int item) { const char* p = buffer; int len = strlen(buffer); int count = 0; for (int i = 0; i < len; i++) { if (' ' == *p) { count++; if (count == item - 1) { p++; break; } } p++; } return p; } bool cmp(const pair& a, const pair& b) { return a.second > b.second; } /* ----------------------- 根据先后两个时间的CPU信息, 计算CPU的总占用量和各个进程的占用量 ----------------------- */ void ResourceWatcherFSM::GetSystemCPUStatus() { //int cpu_num = sysconf(_SC_NPROCESSORS_CONF); //CPU核数 CPUInfo* cpuOld = new CPUInfo; CPUInfo* cpuNew = new CPUInfo; const char* tPath = "/proc"; map nameProcess; // map usageProcess; // long oldTotalTime = GetCPURunTime(cpuOld); //旧CPU运行总时间 if (oldTotalTime == -1) { return; } map oldProcCPUTime; // struct dirent* oldDirp; DIR* oldDp = opendir(tPath); if (oldDp != NULL) { while ((oldDirp = readdir(oldDp)) != NULL) { //获取旧时刻 每一个进程的pid、CPU运行时间、进程名 string fileName = oldDirp->d_name; BOOL isPid = TRUE; for (int i = 0; i < fileName.length(); ++i) //判断进程id的文件夹 是否文件名是否纯数字 { if (!isdigit(fileName[i])) { isPid = FALSE; break; } } if (!isPid) continue; DWORD pid; long oldTime; ProcCPUInfo* oldProcCPU = new ProcCPUInfo; sscanf(oldDirp->d_name, "%d", &pid); //读取文件夹名 oldTime = ReadProcCPURunTime(pid, oldProcCPU); if (oldTime == -1) { return; } oldProcCPUTime[pid] = oldTime; nameProcess[pid] = oldProcCPU->pname; delete oldProcCPU; } closedir(oldDp); } sleep(1); long newTotalTime = GetCPURunTime(cpuNew); //新CPU运行总时间 if (newTotalTime == -1) { return; } map newProcCPUTime; // struct dirent* newDirp; DIR* newDp = opendir(tPath); if (newDp != NULL) { while ((newDirp = readdir(newDp)) != NULL) { //获取新时刻 每一个进程的pid、CPU运行时间、进程名 string fileName = newDirp->d_name; BOOL isPid = TRUE; for (int i = 0; i < fileName.length(); ++i) //判断进程id的文件夹 是否文件名是否纯数字 { if (!isdigit(fileName[i])) { isPid = FALSE; break; } } if (!isPid) continue; DWORD pid; long newTime; ProcCPUInfo* newProcCPU = new ProcCPUInfo; sscanf(newDirp->d_name, "%d", &pid); //读取文件夹名 newTime = ReadProcCPURunTime(pid, newProcCPU); if (newTime == -1) { return; } newProcCPUTime[pid] = newTime; string tName = newProcCPU->pname; tName.erase(tName.begin()); tName.erase(tName.begin() + (tName.length() - 1)); nameProcess[pid] = tName; delete newProcCPU; } closedir(newDp); } map::iterator it; for (it = newProcCPUTime.begin(); it != newProcCPUTime.end(); ++it) { DWORD tPid = it->first; //进程的占用率 = 单位时间间隔里进程的CPU时间片占用 / 单位时间间隔里CPU的整体时间片 DOUBLE tRatio = 100.0 * (newProcCPUTime[tPid] - oldProcCPUTime[tPid]) / (newTotalTime - oldTotalTime); usageProcess[tPid] = tRatio; } CSystemRunInfo runInfo = { 0 }; GetEntityBase()->GetFunction()->GetSystemRunInfo(runInfo); for (int i = 0; i < runInfo.strRunningEntityNames.GetCount(); i++) //实体进程的名称默认全为sphost,需转换为对应实体名 { string entityName = runInfo.strRunningEntityNames[i].GetData(); CEntityRunInfo entityInfo = { 0 }; GetEntityBase()->GetFunction()->GetEntityRunInfo(entityName.c_str(), entityInfo); nameProcess[entityInfo.dwProcessID] = entityName; } vector> vec(usageProcess.begin(), usageProcess.end()); sort(vec.begin(), vec.end(), cmp); //根据CPU使用率从大到小进行排序 int cpuTop = 10; int len = MIN(cpuTop, vec.size()); //确认要展示的进程数量 string procWarn = ""; for (int i = 0; i < len; ++i) //构建进程的CPU使用告警信息 { char* tUsage = new char[20]; sprintf(tUsage, "%.2lf", vec[i].second); procWarn = procWarn + ",\"" + nameProcess[vec[i].first] + "\":\"" + string(tUsage) + "%\""; delete tUsage; } unsigned long oldInfo, newInfo; double cUsedRate = 0; //第一次(用户+优先级+系统+空闲)的时间 //oldInfo = (unsigned long)(cpuOld->user + cpuOld->nice + cpuOld->system + cpuOld->idle + cpuOld->lowait + cpuOld->irq + cpuOld->softirq); //第二次(用户+优先级+系统+空闲)的时间 //newInfo = (unsigned long)(cpuNew->user + cpuNew->nice + cpuNew->system + cpuNew->idle + cpuNew->lowait + cpuNew->irq + cpuNew->softirq); double totalTime = newTotalTime - oldTotalTime; double freeTime = cpuNew->idle - cpuOld->idle; cUsedRate = (totalTime - freeTime) / totalTime; if (m_cpuHighPercent <= 0) { m_cpuHighPercent = 80; //默认告警百分比80% } if (cpuWarnThreshold <= 0) { cpuWarnThreshold = 10; //默认满10次告一次警 } if ((cUsedRate * 100) > m_cpuHighPercent) { cpuWarnTime = cpuWarnTime % cpuWarnThreshold; if (cpuWarnTime == 0) //每达到一次阈值告警一次 { stringstream tss; tss << std::setiosflags(std::ios::fixed) << std::setprecision(2) << cUsedRate * 100; string warn = "{ \"total_used\":\"" + tss.str() + "%\"" + procWarn + "}"; LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_CPU_TOO_HIGH, CSimpleStringA::Format("%s", warn.c_str())); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A03").setAPI("CpuUsedCheck")(warn.c_str()); } cpuWarnTime++; } delete cpuNew; delete cpuOld; } void ResourceWatcherFSM::GetSystemMemoryStatus() { MemInfo* memInfo = new MemInfo(); FILE* fd; char buff[256]; fd = fopen("/proc/meminfo", "r"); if (!fd) { //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Read Memory INFO FAILED!"); return; } fgets(buff, sizeof(buff), fd); sscanf(buff, "%s %lu ", memInfo->infoName1, &memInfo->memTotal); fgets(buff, sizeof(buff), fd); sscanf(buff, "%s %lu ", memInfo->infoName2, &memInfo->memFree); fgets(buff, sizeof(buff), fd); sscanf(buff, "%s %lu ", memInfo->infoName3, &memInfo->memAvail); fclose(fd); double mUsedRate = 0; mUsedRate = (double)(memInfo->memTotal - memInfo->memAvail) / (double)memInfo->memTotal; char szResult[DEFAULT_OUTPUT_FORMAT_SIZE]; char szResult2[DEFAULT_OUTPUT_FORMAT_SIZE]; char szResult3[DEFAULT_OUTPUT_FORMAT_SIZE]; ByteSprintf(szResult, (double)(memInfo->memTotal) * 1024, 'G'); // 内存信息在 /proc/meminfo 中的单位为 KB ByteSprintf(szResult2, (double)(memInfo->memFree) * 1024, 'G'); ByteSprintf(szResult3, (double)(memInfo->memAvail) * 1024, 'G'); if (m_memHighPercent <= 0) { m_memHighPercent = 80; //默认告警百分比80% } if (memWarnThreshold <= 0) { memWarnThreshold = 10; //默认告警阈值10次 } if ((mUsedRate * 100) > m_memHighPercent) { memWarnTime = memWarnTime % memWarnThreshold; if (memWarnTime == 0) //每达到阈值告警一次 { char usedResult[DEFAULT_OUTPUT_FORMAT_SIZE]; ByteSprintf(usedResult, (double)(memInfo->memTotal) * 1024 * mUsedRate, 'G'); stringstream ss1; ss1 << std::setiosflags(std::ios::fixed) << std::setprecision(2) << mUsedRate * 100; string warn = "{ \"total\":\"" + string(szResult) + "\"," + "\"used\":\"" + ss1.str() + "%\"," + MemoryProcessStatus(); LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_MEMORY_TOO_HIGH, CSimpleStringA::Format("%s", warn.c_str())); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A04").setAPI("MemUsedCheck")(warn.c_str()); } memWarnTime++; } } void ResourceWatcherFSM::GetDiskStatusFrom(LPCTSTR path) { if (m_diskHighPercent <= 0) { m_diskHighPercent = 90; //默认硬盘告警百分比90% } unsigned long long uiTotalBytes; unsigned long long uiFreeDiskBytes; char szResult[DEFAULT_OUTPUT_FORMAT_SIZE]; char szResult2[DEFAULT_OUTPUT_FORMAT_SIZE]; BOOL readFlag = DiskInfo::GetDiskSpace(path, uiTotalBytes, uiFreeDiskBytes); double dUsedRate = 1 - (uiFreeDiskBytes * kConversion[3]) / (uiTotalBytes * kConversion[3]); ByteSprintf(szResult, (double)uiTotalBytes); ByteSprintf(szResult2, (double)uiFreeDiskBytes); if (readFlag && (dUsedRate * 100 < m_diskHighPercent)) { //DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("[Disk# %s] total: %s, free: %s, [Disk] used rate: %.1lf%%.", path, szResult, szResult2, dUsedRate * 100); } else { CSimpleStringA warnStr = CSimpleStringA::Format("\"Disk\":\"%s\",\"total\":\"%s\",\"free\":\"%s\",\"used rate\":\"%.1lf%%\"", path, szResult, szResult2, dUsedRate * 100); LogWarn(Severity_Middle, Error_Resource, LOG_EVT_RESOURCE_HARDDISK_TOO_HIGH, warnStr.GetData()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5A05").setAPI("DiskUsedCheck")(warnStr.GetData()); CheckDiskFileSpaceTask* task4 = new CheckDiskFileSpaceTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(task4); } } void ResourceWatcherFSM::GetSystemDiskStatus() { GetDiskStatusFrom("/"); } void ResourceWatcherFSM::switchWindowsEffect(const char* cfgFilePath, bool enable) { char tmp[33]; memset(tmp, 0, 33); inifile_read_str_s("Compositing", "Enabled", "", tmp, 32, cfgFilePath); if (strlen(tmp) == 0 || stricmp(tmp, "false") == 0) { if (enable) { inifile_write_str(cfgFilePath, "Compositing", "Enabled", "true"); LogWarn(Severity_Low, Error_InvalidState, LOG_RESOURCEWATCHER_COMPOSITING_CHANGE_ON, "to active window effect"); } } else if (stricmp(tmp, "true") == 0) { if (!enable) { inifile_write_str(cfgFilePath, "Compositing", "Enabled", "false"); LogWarn(Severity_Low, Error_InvalidState, LOG_RESOURCEWATCHER_COMPOSITING_CHANGE_OFF, "to inactive window effect"); } } } void ResourceWatcherFSM::RecoverDDEClipboardEnable() { const std::string clipboardPath = "/usr/bin/dde-clipboard"; const std::string clipboardPathBak = "/usr/bin/dde-clipboard.bak"; if (!ExistsFileA(clipboardPath.c_str()) && ExistsFileA(clipboardPathBak.c_str())) { fileutil_copy_file(clipboardPath.c_str(), clipboardPathBak.c_str()); //fileutil_delete_file(clipboardPathBak.c_str()); LogWarn(Severity_Low, Error_Debug, LOG_RESOURCEWATCHER_CLIPBOARD_RECOVER_ENABLE, "recover clipboard succ."); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("%s exists.", clipboardPath.c_str()); } } void ResourceWatcherFSM::ConfirmDDEClipboardDisable() { const std::string clipboardPath = "/usr/bin/dde-clipboard"; const std::string clipboardPathBak = "/usr/bin/dde-clipboard.bak"; char* clipboards[] = { "dde-clipboard", "dde-clipboardloader" }; if (!ExistsFileA(clipboardPath.c_str())) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("There are no any %s files.", clipboardPath.c_str()); if (ExistsFileA(clipboardPathBak.c_str())) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("%s exists.", clipboardPathBak.c_str()); } return; } if (0 != fileutil_copy_file(clipboardPathBak.c_str(), clipboardPath.c_str())) { LogWarn(Severity_Low, Error_Unexpect, LOG_RESOURCEWATCHER_CLIPBOARD_REMOVE_FAILED, "remove clipboard failed"); } else { fileutil_delete_file(clipboardPath.c_str()); osutil_terminate_related_process(clipboards, array_size(clipboards), 0); LogWarn(Severity_Low, Error_Process, LOG_RESOURCEWATCHER_CLIPBOARD_REMOVE_SUCC, "remove clipboard succ."); } } void ResourceWatcherFSM::ConfirmNotificationCenterDisable() { const char* osd_file_path = "/usr/lib/deepin-daemon/dde-osd"; const char* osd_bak_file_path = "/usr/lib/deepin-daemon/dde-osd.bak"; CSmartPointer spConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_Cache, spConfig); int flag = 0; spConfig->ReadConfigValueInt("UOSFeatures", "NotifyCenterSupport", flag); if (flag == 1) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("allow the dde-osd process alive."); if (!ExistsFileA(osd_file_path) && ExistsFileA(osd_bak_file_path)) { fileutil_copy_file(osd_file_path, osd_bak_file_path); LogWarn(Severity_Low, Error_Debug, LOG_RESOURCEWATCHER_OSD_RECOVER_ENABLE, "recover dde osd succ."); } } else { if (ExistsFileA(osd_file_path) && !ExistsFileA(osd_bak_file_path)) { char* relates[] = { "dde-osd" }; if (0 != fileutil_copy_file(osd_bak_file_path, osd_file_path)) { LogWarn(Severity_Low, Error_Unexpect, LOG_RESOURCEWATCHER_CLIPBOARD_REMOVE_FAILED, "remove dde osd failed"); } else { osutil_terminate_related_process(relates, array_size(relates), 0); fileutil_delete_file(osd_file_path); LogWarn(Severity_Low, Error_Process, LOG_RESOURCEWATCHER_OSD_REMOVE_SUCC, "remove dde osd succ."); } } } } void ResourceWatcherFSM::ConfirmWindowEffectHasBeenOpen() { array_header_t* arr; arr = fileutil_get_sub_dirs_a("/home"); if (arr) { int i; for (i = 0; i < arr->nelts; ++i) { char szDestSubDir[256] = { 0 }; char* dir = ARRAY_IDX(arr, i, char*); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sub dir: %s", dir); strcpy(szDestSubDir, dir); strcat(szDestSubDir, SPLIT_SLASH_STR); strcat(szDestSubDir, ".config/kwinrc"); if (ExistsFileA(szDestSubDir)) { switchWindowsEffect(szDestSubDir, true); } } toolkit_array_free2(arr); } } #endif // RVC_OS_LINUX