590 lines
14 KiB
C++
590 lines
14 KiB
C++
#include "daemon.h"
|
|
|
|
#include <QDebug>
|
|
|
|
#pragma comment (lib,"Advapi32.lib")
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint16_t pid;
|
|
string process_name;
|
|
} RuningProcess;
|
|
|
|
vector<RuningProcess> RangeProcess();
|
|
|
|
vector<string> StripList(const char *in, const char *d)
|
|
{
|
|
vector<string> ret;
|
|
map<uint16_t,bool> pos;
|
|
vector<uint16_t> pos_strip_continue;
|
|
int lastpos = -1;
|
|
|
|
if ((nullptr == in) || (nullptr == d))
|
|
{
|
|
return ret;
|
|
}
|
|
int len = strlen(in);
|
|
int sublen = strlen(d);
|
|
if (len <= 0)
|
|
return ret;
|
|
if (sublen <= 0)
|
|
return ret;
|
|
|
|
for (int i = 0; i < (len - sublen + 1); i++)
|
|
{
|
|
bool found = true;
|
|
for (int j = 0; j < strlen(d); j++)
|
|
{
|
|
if (in[i + j] != d[j])
|
|
{
|
|
found = false;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
pos.insert(make_pair(i,true));
|
|
i += sublen - 1;
|
|
continue;
|
|
}
|
|
}
|
|
if (pos.size() == 0)
|
|
{
|
|
ret.push_back(string(in));
|
|
return ret;
|
|
}
|
|
bool started = true;
|
|
uint16_t startpos = 0;
|
|
uint16_t endpos = 0;
|
|
|
|
for(int i = 0;i < len - 1;i++){
|
|
|
|
if(pos[i] == true){
|
|
if(started){
|
|
startpos = i;
|
|
started = false;
|
|
}
|
|
if((pos[i + sublen] != true)){
|
|
endpos = i;
|
|
// std::cout<<startpos<<" "<<endpos<<"\r\n";
|
|
ret.push_back(string(&in[startpos],&in[endpos + 1]));
|
|
started = true;
|
|
}
|
|
}
|
|
if(i == (len - 2)){
|
|
i = len - 1;
|
|
if(pos[i] == true){
|
|
if(started){
|
|
startpos = i;
|
|
endpos = i;
|
|
// std::cout<<startpos<<" "<<endpos<<"\r\n";
|
|
ret.push_back(string(&in[startpos],&in[endpos + 1]));
|
|
}else{
|
|
endpos = i;
|
|
// std::cout<<startpos<<" "<<endpos<<"\r\n";
|
|
ret.push_back(string(&in[startpos],&in[endpos + 1]));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
#ifdef linux
|
|
|
|
inline bool existed(const std::string &name)
|
|
{
|
|
return (access(name.c_str(), F_OK) != -1);
|
|
}
|
|
|
|
void _process_start(string path)
|
|
{
|
|
|
|
auto file = popen(path.c_str(), "r");
|
|
|
|
if (file < 0)
|
|
{
|
|
|
|
fprintf(stderr, "execl failed:%s", strerror(errno));
|
|
|
|
return;
|
|
}
|
|
|
|
pclose(file);
|
|
}
|
|
|
|
vector<RuningProcess> RangeProcess()
|
|
{
|
|
|
|
FILE *pstr;
|
|
|
|
char cmd[128], buff[512], *p;
|
|
|
|
vector<RuningProcess> ret;
|
|
|
|
int iPID;
|
|
|
|
int pidPosition = 1;
|
|
|
|
int pInfoPosition = 7;
|
|
|
|
memset(cmd, 0, sizeof(cmd));
|
|
|
|
sprintf(cmd, "ps ");
|
|
|
|
pstr = popen(cmd, "r");
|
|
|
|
if (pstr == NULL)
|
|
{
|
|
|
|
return ret;
|
|
}
|
|
|
|
memset(buff, 0, sizeof(buff));
|
|
|
|
bool first = true;
|
|
|
|
while (1)
|
|
{
|
|
|
|
RuningProcess ins;
|
|
|
|
fgets(buff, 512, pstr);
|
|
|
|
if (first)
|
|
{
|
|
|
|
first = false;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (feof(pstr))
|
|
|
|
{
|
|
|
|
break;
|
|
}
|
|
|
|
auto trip = StripList(buff, " ");
|
|
|
|
ins.pid = atoi(trip[0].c_str());
|
|
|
|
ins.process_name = trip[3];
|
|
|
|
ret.push_back(ins);
|
|
}
|
|
|
|
pclose(pstr);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
|
|
static BOOL KillProcess(DWORD dwPid)
|
|
|
|
{
|
|
HANDLE hPrc;
|
|
if (0 == dwPid)
|
|
return FALSE;
|
|
hPrc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); // Opens handle to the process.
|
|
if (!TerminateProcess(hPrc, 0)) // Terminates a process.
|
|
{
|
|
|
|
CloseHandle(hPrc);
|
|
|
|
return FALSE;
|
|
}
|
|
else
|
|
WaitForSingleObject(hPrc, 2000); // At most ,waite 2000 millisecond.
|
|
CloseHandle(hPrc);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL KillProcessByName(const TCHAR *lpszProcessName)
|
|
{
|
|
unsigned int pid = -1;
|
|
BOOL retval = TRUE;
|
|
if (lpszProcessName == NULL)
|
|
return -1;
|
|
|
|
DWORD dwRet = 0;
|
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
PROCESSENTRY32 processInfo;
|
|
processInfo.dwSize = sizeof(PROCESSENTRY32);
|
|
int flag = Process32First(hSnapshot, &processInfo);
|
|
// Find the process with name as same as lpszProcessName
|
|
|
|
while (flag != 0)
|
|
{
|
|
printf("kill process find %s\r\n", processInfo.szExeFile);
|
|
char dest[140];
|
|
if (lstrcmpW(processInfo.szExeFile, lpszProcessName) == 0)
|
|
{
|
|
// Terminate the process.
|
|
pid = processInfo.th32ProcessID;
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
|
|
printf("kill process pid %d\r\n", pid);
|
|
if (TerminateProcess(hProcess, 0) != TRUE)
|
|
{ // Failed to terminate it.
|
|
retval = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
flag = Process32Next(hSnapshot, &processInfo);
|
|
} // while (flag != 0)
|
|
CloseHandle(hSnapshot);
|
|
if (pid == -1)
|
|
return FALSE;
|
|
return retval;
|
|
}
|
|
|
|
static BOOL SetProcessPrivilege(const char *lpName, BOOL opt)
|
|
|
|
{
|
|
HANDLE tokenhandle;
|
|
TOKEN_PRIVILEGES NewState;
|
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenhandle))
|
|
{
|
|
wchar_t dest[150];
|
|
mbstowcs(dest,lpName,strlen(lpName));
|
|
LookupPrivilegeValue(NULL, dest, &NewState.Privileges[0].Luid);
|
|
NewState.PrivilegeCount = 1;
|
|
NewState.Privileges[0].Attributes = opt != 0 ? 2 : 0;
|
|
AdjustTokenPrivileges(tokenhandle, FALSE, &NewState, sizeof(NewState), NULL, NULL);
|
|
CloseHandle(tokenhandle);
|
|
return 1;
|
|
}
|
|
else
|
|
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// static int RangeProcess()
|
|
// {
|
|
// DWORD Proc_pid[1024], Retn_bytes, Proc_count, Retn_bytes2;
|
|
|
|
// unsigned int i;
|
|
|
|
// HMODULE hMod[1024];
|
|
|
|
// HANDLE hProcess;
|
|
|
|
// char szModName[MAX_PATH];
|
|
|
|
// if (EnumProcesses(Proc_pid, sizeof(Proc_pid), &Retn_bytes))
|
|
|
|
// {
|
|
|
|
// Proc_count = Retn_bytes / sizeof(DWORD);
|
|
|
|
// SetProcessPrivilege("SeDebugPrivilege", 1);
|
|
|
|
// for (i = 0; i < Proc_count; i++)
|
|
|
|
// {
|
|
|
|
// hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Proc_pid[i]);
|
|
|
|
// if (hProcess != NULL)
|
|
|
|
// {
|
|
|
|
// EnumProcessModules(hProcess, hMod, sizeof(hMod), &Retn_bytes2);
|
|
|
|
// GetModuleFileNameEx(hProcess, hMod[0], szModName, sizeof(szModName));
|
|
|
|
// // printf("PID=%d Path=%s\n", Proc_pid[i], szModName);
|
|
// }
|
|
|
|
// CloseHandle(hProcess);
|
|
// }
|
|
|
|
// SetProcessPrivilege("SeDebugPrivilege", 0);
|
|
// }
|
|
|
|
// return 0;
|
|
// }
|
|
|
|
static int test_fork()
|
|
{
|
|
char szCommandLine[] = "D:\\game\\The Legend of Zelda Breath of the Wild\\cemu\\cemu.exe";
|
|
STARTUPINFO si = {sizeof(si)};
|
|
PROCESS_INFORMATION pi;
|
|
si.dwFlags = STARTF_USESHOWWINDOW; //指定wShowWindow成员有效
|
|
si.wShowWindow = TRUE; //此成员设为TRUE的话则显示新建进程的主窗
|
|
wchar_t dest[350];
|
|
mbstowcs(dest,szCommandLine,strlen(szCommandLine));
|
|
BOOL bRet = CreateProcess(
|
|
NULL, //不在此指定可执行文件的文件名
|
|
dest, //命令行参
|
|
NULL, //默认进程安全
|
|
NULL, //默认进程安全
|
|
FALSE, //指定当前进程内句柄不可以被子进程继承
|
|
CREATE_NEW_CONSOLE, //为新进程创建一个新的控制台窗口
|
|
NULL, //使用本进程的环境变量
|
|
NULL, //使用本进程的驱动器和目录
|
|
&si,
|
|
&pi);
|
|
if (bRet)
|
|
{
|
|
|
|
//不使用的句柄最好关
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
printf("new process id %d\n", pi.dwProcessId);
|
|
printf("new thread id %d\n", pi.dwThreadId);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
DaemonizeMonitor::DaemonizeMonitor(string path)
|
|
{
|
|
#ifdef linux
|
|
auto process = RangeProcess();
|
|
for (auto itr = process.begin(); itr != process.end(); itr++)
|
|
{
|
|
std::cout << itr->process_name << std::endl;
|
|
m_pids[itr->process_name.substr(0, itr->process_name.size() - 1)] = itr->pid;
|
|
}
|
|
#endif
|
|
auto strip = StripList(path.c_str(), "/");
|
|
if(strip.size() > 0){
|
|
std::cout<< strip[strip.size() - 1]<<std::endl;
|
|
if(m_running_pid[strip[strip.size() - 1]] > 0){
|
|
}else{
|
|
this->AddNewProcess(path);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef linux
|
|
void start_process(string path)
|
|
{
|
|
|
|
std::thread p(_process_start, path);
|
|
|
|
p.detach();
|
|
}
|
|
#endif
|
|
|
|
int DaemonizeMonitor::AddNewProcess(string path)
|
|
{
|
|
if (path == "")
|
|
{
|
|
return -1;
|
|
}
|
|
this->m_path_process.push_back(path);
|
|
if(mCallback.operator bool())
|
|
mCallback();
|
|
|
|
#ifdef linux
|
|
if (!existed(path))
|
|
{
|
|
return -1;
|
|
}
|
|
start_process(path);
|
|
usleep(100000);
|
|
auto strip = StripList(path.c_str(), "/");
|
|
|
|
auto process = RangeProcess();
|
|
for (auto itr = process.begin(); itr != process.end(); itr++)
|
|
{
|
|
m_pids[itr->process_name.substr(0, itr->process_name.size() - 1)] = itr->pid;
|
|
}
|
|
if (m_pids[strip[strip.size() - 1]] > 0)
|
|
this->m_running_pid[strip[strip.size() - 1]] = m_pids[strip[strip.size() - 1]];
|
|
#endif
|
|
#ifdef _WIN32
|
|
STARTUPINFO si = {sizeof(si)};
|
|
PROCESS_INFORMATION pi;
|
|
si.dwFlags = STARTF_USESHOWWINDOW; //指定wShowWindow成员有效
|
|
si.wShowWindow = TRUE; //此成员设为TRUE的话则显示新建进程的主窗
|
|
|
|
wchar_t dest[150] = {0};
|
|
mbstowcs(dest,(LPSTR)path.c_str(),strlen((LPSTR)path.c_str()));
|
|
BOOL bRet = CreateProcess(
|
|
NULL, //不在此指定可执行文件的文件名
|
|
dest, //命令行参
|
|
NULL, //默认进程安全
|
|
NULL, //默认进程安全
|
|
FALSE, //指定当前进程内句柄不可以被子进程继承
|
|
CREATE_NEW_CONSOLE, //为新进程创建一个新的控制台窗口
|
|
NULL, //使用本进程的环境变量
|
|
NULL, //使用本进程的驱动器和目录
|
|
&si,
|
|
&pi);
|
|
|
|
if (bRet)
|
|
{
|
|
//不使用的句柄最好关
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
printf("new process id %d\n", pi.dwProcessId);
|
|
this->m_running_pid[path] = pi.dwProcessId;
|
|
return 0;
|
|
}
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
int DaemonizeMonitor::StartMonitor()
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
DWORD Proc_pid[10240], Retn_bytes, Proc_count, Retn_bytes2;
|
|
unsigned int i;
|
|
HMODULE hMod[1024];
|
|
HANDLE hProcess;
|
|
char szModName[MAX_PATH];
|
|
while (true)
|
|
{
|
|
/* code */
|
|
Sleep(5000);
|
|
for (auto itr = m_running_pid.begin(); itr != m_running_pid.end(); itr++)
|
|
{
|
|
bool found = false;
|
|
if (EnumProcesses(Proc_pid, sizeof(Proc_pid), &Retn_bytes))
|
|
{
|
|
Proc_count = Retn_bytes / sizeof(DWORD);
|
|
SetProcessPrivilege("SeDebugPrivilege", 1);
|
|
for (i = 0; i < Proc_count; i++)
|
|
{
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Proc_pid[i]);
|
|
if (hProcess != NULL)
|
|
{
|
|
wchar_t dest[150] = {0};
|
|
wchar_t dest2[150] = {0};
|
|
|
|
mbstowcs(dest,szModName,strlen(szModName));
|
|
EnumProcessModules(hProcess, hMod, sizeof(hMod), &Retn_bytes2);
|
|
GetModuleFileNameEx(hProcess, hMod[0], dest, sizeof(szModName));
|
|
qDebug()<<QString::asprintf("PID=%d %d", Proc_pid[i],itr->second)
|
|
<<QString::fromWCharArray(dest,lstrlenW(dest));
|
|
|
|
mbstowcs(dest2,itr->first.c_str(),itr->first.size());
|
|
|
|
if (lstrcmpW(dest,dest2) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
CloseHandle(hProcess);
|
|
}
|
|
SetProcessPrivilege("SeDebugPrivilege", 0);
|
|
if (!found)
|
|
{
|
|
// 没找到该应用实例就重启应
|
|
auto it = m_path_process.begin();
|
|
while (it != m_path_process.end())
|
|
{
|
|
if (*it == itr->first)
|
|
{
|
|
it = m_path_process.erase(it);
|
|
}
|
|
else
|
|
it++;
|
|
}
|
|
for (auto it = m_path_process.begin(); it != m_path_process.end(); it++)
|
|
{
|
|
std::cout << *it << std::endl;
|
|
}
|
|
this->AddNewProcess(itr->first);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
#endif
|
|
|
|
#ifdef linux
|
|
while (true){
|
|
auto process = RangeProcess();
|
|
usleep(50000);
|
|
for (auto itr = m_running_pid.begin(); itr != m_running_pid.end(); itr++)
|
|
{
|
|
bool found = false;
|
|
for (auto itr2 = process.begin(); itr2 != process.end(); itr2++)
|
|
{
|
|
if (itr->second == itr2->pid)
|
|
{
|
|
// std::cout << itr->second << itr2->pid << std::endl;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
// 没找到该应用实例就重启应
|
|
auto it = m_path_process.begin();
|
|
while (it != m_path_process.end())
|
|
{
|
|
if (*it == itr->first)
|
|
{
|
|
it = m_path_process.erase(it);
|
|
}
|
|
else
|
|
it++;
|
|
}
|
|
for (auto it = m_path_process.begin(); it != m_path_process.end(); it++)
|
|
{
|
|
std::cout << *it << std::endl;
|
|
}
|
|
std::cout << "add new process" << std::endl;
|
|
if (0 > this->AddNewProcess(itr->first))
|
|
std::cout << "error not found" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int DaemonizeMonitor::SetRestartCallback(RestartCallback b)
|
|
{
|
|
this->mCallback = b;
|
|
return 0;
|
|
}
|
|
|
|
int DaemonizeMonitor::StopMonitor(string)
|
|
{
|
|
#ifdef _WIN32
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int DaemonizeMonitor::StopProcess(string path)
|
|
{
|
|
if (path == "")
|
|
{
|
|
return -1;
|
|
}
|
|
#ifdef _WIN32
|
|
if (m_running_pid.find(path) != m_running_pid.end())
|
|
{
|
|
DWORD pid = m_running_pid.at(path);
|
|
m_running_pid.erase(path);
|
|
if (KillProcess(pid))
|
|
return 0;
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
#endif
|
|
#ifdef linux
|
|
#endif
|
|
}
|