// ProMon.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#include <io.h>
#include <direct.h>
#define WORKING_PROCESS_MUTEX_NAME _T("WORKING_PROCESS_MUTEX_NAME_SAFTYAGENT")
#define PROTECT_PROCESS_MUTEX_NAME _T("PROTECT_PROCESS_MUTEX_NAME_SAFTYAGENT")
#define PROTECT_MON _T("promon.exe")
void BackupSelf();
void CreateSelf();
void ProcessParam(LPTSTR lpCmdLine);
HANDLE FindProcess(LPTSTR ProcessPath, DWORD FilterID = 0);
DWORD WINAPI ProtectEntry(LPVOID param);
BOOL CreatMultiDirectory(LPCTSTR Path);
TCHAR propath[MAX_PATH];
TCHAR path[MAX_PATH];
HANDLE hMutex;
BOOL protect = FALSE;
BYTE* filebody = NULL;
TCHAR selfPath[MAX_PATH];
int selflen = 0;
FILETIME createtime;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
if (!lpCmdLine || _tcslen(lpCmdLine) == 0)
return 0;
GetModuleFileName(hInstance, selfPath, MAX_PATH);
BackupSelf();
ProcessParam(lpCmdLine);
LPCTSTR selfname = protect ? PROTECT_PROCESS_MUTEX_NAME : WORKING_PROCESS_MUTEX_NAME;
LPCTSTR othername = protect ? WORKING_PROCESS_MUTEX_NAME : PROTECT_PROCESS_MUTEX_NAME;
HANDLE handle = OpenMutex(MUTEX_ALL_ACCESS, FALSE, selfname);
if (handle != NULL)
{
CloseHandle(handle);
return 0;
}
hMutex = CreateMutex(NULL, FALSE, selfname);
if (!protect)
CloseHandle(CreateThread(NULL, 0, ProtectEntry, 0, 0, NULL));
while (1)
{
HANDLE mutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, othername);
if (!mutex)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
if (!CreateProcess(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
CreateSelf();
CreateProcess(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else
{
CloseHandle(mutex);
HANDLE hProcess = FindProcess(selfPath, GetCurrentProcessId());
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
}
}
CloseHandle(hMutex);
delete[] filebody;
return 0;
}
DWORD WINAPI ProtectEntry(LPVOID param)
{
HANDLE hProcess = FindProcess(propath);
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hProcess);
STARTUPINFO si;
PROCESS_INFORMATION pi;
while (1)
{
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess(NULL, propath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
return 0;
}
void ProcessParam(LPTSTR lpCmdLine)
{
LPTSTR pfinger = lpCmdLine;
int start = 0;
int end = 0;
while (1)
{
switch(*pfinger)
{
case 0:
case ' ':
case '\t':
case '\n':
{
if (start == end)
end = start = (int)(pfinger - lpCmdLine);
else
{
end = (int)(pfinger - lpCmdLine);
LPTSTR param = new TCHAR[end - start + 1];
_tcsncpy(param, lpCmdLine + start, end - start);
param[end - start] = 0;
_tcslwr(param);
if (_tcscmp(param, _T("pro")) == 0)
{
protect = TRUE;
}
else
{
_tcsncpy(param, lpCmdLine + start, end - start);
param[end - start] = 0;
*propath = 0;
BOOL needquot = *param != '\"';
if (needquot)
_tcscat(propath, _T("\""));
_tcscat(propath, param);
if (needquot)
_tcscat(propath, _T("\""));
}
delete[] param;
}
if (*pfinger != 0)
{
++pfinger;
start = (int)(pfinger - lpCmdLine);
continue;
}
break;
}
case '\"':
{
while (*(++pfinger) != '\"')
++end;
}
default:
++pfinger;
++end;
continue;
}
if (*pfinger == 0)
break;
}
_tcscpy(path, selfPath);
if (!protect)
_tcscat(path, _T(" pro"));
_tcscat(path, _T(" "));
_tcscat(path, propath);
}
void BackupSelf()
{
FILE* pFile = _tfopen(selfPath, _T("rb"));
fseek(pFile, 0, SEEK_END);
selflen = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
filebody = new BYTE[selflen];
int offset = 0;
while (offset < selflen)
offset += (int)fread(filebody + offset, 1, selflen - offset, pFile);
fclose(pFile);
HANDLE hFile = CreateFile(selfPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hFile)
{
GetFileTime(hFile, &createtime, NULL, NULL);
CloseHandle(hFile);
}
}
void CreateSelf()
{
TCHAR path[MAX_PATH];
_tcscpy(path, selfPath);
int len = (int)_tcslen(path);
while (path[len - 1] != '\\')
--len;
path[len - 1] = 0;
CreatMultiDirectory(path);
FILE* pFile = _tfopen(selfPath, _T("w+b"));
int offset = 0;
while (offset < selflen)
offset += (int)fwrite(filebody + offset, 1, selflen - offset, pFile);
fclose(pFile);
HANDLE hFile = CreateFile(selfPath, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hFile)
{
SetFileTime(hFile, &createtime, &createtime, &createtime);
CloseHandle(hFile);
}
}
HANDLE FindProcess(LPTSTR ProcessPath, DWORD FilterID)
{
HANDLE hProcess = NULL;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnapshot, &pe);
do {
if (pe.th32ProcessID == FilterID)
continue;
if(_tcslen(pe.szExeFile)>0)
{
LPTSTR filename = _tcsstr(ProcessPath, pe.szExeFile);
if (filename && *(filename-1) == '\\' && _tcsnicmp(filename, pe.szExeFile, _tcslen(pe.szExeFile)) == 0)
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
break;
}
}
}
while (Process32Next(hSnapshot, &pe));
CloseHandle(hSnapshot);
return hProcess;
}
BOOL CreatMultiDirectory(LPCTSTR Path)
{
TCHAR MultiDirPath[MAX_PATH];
_tcscpy(MultiDirPath, Path);
int len = (int)_tcslen(Path);
if (MultiDirPath[len - 1] == '\\')
MultiDirPath[len - 1] = 0;
_finddata_t info;
intptr_t finder;
if ((finder = _findfirst(MultiDirPath, &info)) != -1)
{
_findclose(finder);
return TRUE;
}
int offset = 0;
LPTSTR pos = MultiDirPath;
int ret;
while (1)
{
pos = _tcschr(MultiDirPath + offset + 1, '\\');
if (pos)
{
offset = (int)(pos - MultiDirPath);
if (offset == 2)
continue;
MultiDirPath[offset] = 0;
}
else
offset = (int)_tcslen(MultiDirPath);
if((finder = _findfirst(MultiDirPath, &info)) == -1)
{
ret = _mkdir(MultiDirPath);
if (ret == -1)
{
_findclose(finder);
return FALSE;
}
}
if (pos)
MultiDirPath[offset] = '\\';
else
break;
}
_findclose(finder);
return TRUE;
}