#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <io.h>
#include <iostream>
#include <string>
#include <cstring>
#include "tlhelp32.h"

using namespace std;

//隐藏DOS黑窗口
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

//定义路径最大程度
#define MAX_PATH 4096
//定义守护进程名称
#define PROCCESS_NAME "HttpCamera.exe"
//配置文件名称
#define PLUGIN_NAME "plugin.ini"
//定义写入的注册表路径
#define SELFSTART_REGEDIT_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\"

//设置本身开机自启动
BOOL SetSelfStart()
{
  //获取程序完整名称
  char pName[MAX_PATH]={0};
  GetModuleFileNameA(NULL,pName,MAX_PATH);

  //在注册表中写入启动信息
  HKEY hKey=NULL;
  LONG lRet=NULL;
  lRet=RegOpenKeyExA(HKEY_LOCAL_MACHINE,SELFSTART_REGEDIT_PATH,0,KEY_ALL_ACCESS,&hKey);

  //判断是否成功
  if(lRet!=ERROR_SUCCESS)
  {
    return FALSE;
  }

  lRet=RegSetValueExA(hKey,"testProtect",0,REG_SZ,(const unsigned char*)pName,strlen(pName)+sizeof(char));

  //判断是否成功
  if(lRet!=ERROR_SUCCESS)
  {
    return FALSE;
  }

  //关闭注册表
  RegCloseKey(hKey);
  return TRUE;
}

BOOL IsExistProcess(const char* szProcessName)
{
  PROCESSENTRY32 processEntry32;
  HANDLE toolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (((int)toolHelp32Snapshot) != -1)
  {
    processEntry32.dwSize = sizeof(processEntry32);
    if (Process32First(toolHelp32Snapshot, &processEntry32))
    {
      do{
        int iLen = 2 * wcslen(processEntry32.szExeFile);
        char* chRtn = new char[iLen + 1];
        //转换成功返回为非负值
        wcstombs(chRtn, processEntry32.szExeFile, iLen + 1);
        if (strcmp(szProcessName, chRtn) == 0)
        {
          return TRUE;
        }
      } while (Process32Next(toolHelp32Snapshot, &processEntry32));
    }
  CloseHandle(toolHelp32Snapshot);
  }
  return FALSE;
}

int main()
{
  //设置程序开机自启动
  if(!SetSelfStart())
  {
    cout<<"守护进程开机自启动失败"<<endl;
    return -1;
  }

  STARTUPINFOA si;
  //进程对象
  PROCESS_INFORMATION pi;
  //初始化
  ZeroMemory(&si,sizeof(si));
  si.cb=sizeof(si);
  ZeroMemory(&pi,sizeof(pi));

  //获取当前程序的路径
  char pPath[MAX_PATH]={0};
  GetCurrentDirectoryA(MAX_PATH,pPath);

  char szFilePath[MAX_PATH]={0};
  GetModuleFileNameA(NULL, szFilePath, MAX_PATH);
  (strrchr(szFilePath, '\\'))[0] = 0; // 删除文件名,只获得路径
  memcpy(pPath, szFilePath, MAX_PATH);


  char szPluginFilePath[MAX_PATH]={0};
  memcpy(szPluginFilePath, pPath, MAX_PATH);
  strcat_s(szPluginFilePath,"\\");
  strcat_s(szPluginFilePath,PLUGIN_NAME);

  //拼接需要守护的程序
  strcat_s(pPath,"\\");
  strcat_s(pPath,PROCCESS_NAME);
  //if(IsExistProcess(PROCCESS_NAME))
  //{
    // return -1;
  //}

  WCHAR wszPluginFilePath[MAX_PATH] = {0};
  MultiByteToWideChar(CP_ACP, 0, szPluginFilePath, strlen(szPluginFilePath) + 1,
  wszPluginFilePath, sizeof(wszPluginFilePath) / sizeof(wszPluginFilePath[0]));

  //int nOpen = GetPrivateProfileInt(_T("WATCH"), _T("open"), 1, (LPCWSTR)wszPluginFilePath);

  //无限循环,监视守护进程
  do{
    int nOpen = GetPrivateProfileInt(_T("WATCH"), _T("open"), 1, (LPCWSTR)wszPluginFilePath);
    //检查守护程序是否存在
    if(_access(pPath,0)!=-1)
    {
      if(IsExistProcess(PROCCESS_NAME))
      {
        Sleep(1000);//程序已存在
      }
      else
      {

         if(1 == nOpen)
        {
          //创建子进程,判断是否执行成功
          if(!CreateProcessA(NULL,pPath,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi))
          {
            cout<<"守护进程启动失败,程序即将退出"<<endl;
            return -1;
          }

          //启动成功,获取进程的ID
          cout<<"守护进程成功,ID:"<<pi.dwProcessId<<endl;
          //无限等待子进程退出
          WaitForSingleObject(pi.hProcess,INFINITE);
          //如果退出了
          cout<<"守护进程退出了。。。"<<endl;
          //关闭进程和句柄
          CloseHandle(pi.hProcess);
          CloseHandle(pi.hThread);
        }
        else
        {
          //睡一下,重启
          Sleep(1000);
        }
      }
    }
    else
    {
      cout<<"守护程序不存在"<<endl;
    }
  //睡一下,重启
  Sleep(1000);
  }
  while(true);
  return 0;
}

//
//int _tmain(int argc, _TCHAR* argv[])
//{
// return 0;
//}
//