要对Windows9x操作系统下的文件进行保护,只能通过驱动级开发来实现。通常情况下是写一个Installable File System Hook(IFSH,可安装文件系统挂钩程序)加载在系统中,然后在其中监控系统的文件操作。当发现系统在作你希望监控的操作时,进行你需要的操作(此时系统并没有进行实际的操作,你赶在了系统操作之前)。进行此项开发需要相应平台的IFS kit (可安装文件系统开发包),Windows9x的在它们的DDK中已经包含,但Windows NT和Windows 2000的IFS kit需要向微软购买(目前估价$6000,国内好象还没有,你自己找吧,看运气了)。
现在大部分杀毒软件号称的虚拟机技术就是我们将要介绍的基于IFS(可安装文件系统,下同)的文件系统操作技术。不同的是它们是在文件操作之前检查一下特征码,看有没有感染病毒,而我们所要作的是检查一下该文件是否允许存取,对它们作相应的保护。
下面我们以一个用于指定的文件的操作保护的程序为例介绍一下这种技术。
我们把它设计成为对磁盘(逻辑盘)、具体文件作相应保护的工具。为了简化起见,我们只启用了防删除保护。同样的原理你也可以自己扩充功能。
本套程序包括后台VXD驱动程序和前台程序两个部分。
本程序开发环境如下:
Windows 98 第二版
VC++ 6.0专业版
VTOOLSD 3.0(DRIVERSTUDIO 2.0中自带的)
一、 后台VXD程序的生成和编写
我们用VXD辅助开发工具VTOOLSD 3.0版本来生成程序框架。
- 设置一般选项
打开vtoolsd的Quick Vxd后将设备参数页作如下设置:
其中在设备名框中输入的”FILHOOK”将作为生成的设备名出现在系统中,你可以用Vtoolsd自带的 vxd viewer查看系统中加载的驱动程序,如果你已经成功加载此驱动程序,你将看到如下图所示的画面:
证明已经加载入系统中。
2. 程序入口方式设置
一般情况下,我们在windows9x下加载的VXD驱动程序都必需使用”Protected Mode”保护模式方式。关于详细的说明,请参阅本专栏前面的文章中的介绍。
3. 必需响应的系统消息
由于我们的驱动程序要求必需能动态加载,而且能够响应win32应用程序的控制,并与Win32前台程序交互作用,所以必需响应系统的如下三个消息 (由操作系统的虚拟机管理器VMM发给我们的驱动程序的系统通知消息) :
SYS_DYNAMIC_DEVICE_EXIT :驱动程序动态卸载通知消息
SYS_DYNAMIC_DEVICE_INIT :驱动程序动态加载通知消息
W32_DEVICEIOCONTROL :WIN32设备输入输出控制消息(由win32前台程序发给VXD驱动程序的消息)
生成框架后,我们再加入自己的代码。
第一部分:实现文件定义。
// FILEHOOK.cpp - main module for VxD FILEHOOK
#define DEVICE_MAIN
#include “filehook.h”
Declare_Virtual_Device(FILEHOOK) //VXD设备名
#undef DEVICE_MAIN
//此处为我们加入的控制消息定义,注意,这里的消息不是windows消息,而是由DeviceIoControl函数发给VXD的消息。
#define REMOVE_DRV 100 //删除在保护列表中的一个驱动器
#define REMOVE_FILE 101 //删除在文件列表中的一个文件
#define REMOVE_DIR 102 //删除在目录列表中的一个目录名
#define ADD_DIR 103 //添加要保护的目录名到列表中
#define ADD_DRV 104 //添加要保护的驱动器到列表中
#define ADD_FILE 105 //添加要保护的文件名到列表中
#define STARTP 106 //启动保护
#define STOPP 107 //停止保护
#define PREAD 10 //读保护
#define PDELETE 11 //删除保护 ,目前我们只实现此保护
#define PWRITE 12 //写保护
#define PALL 13 //保护所有的操作
#define PCREATE 14 //禁止创建文件
由于时间关系,我们只实现了文件删除保护和驱动器删除保护。其它的保护只是响应不同的系统操作类型而已。(目录操作保护和文件操作保护机理不同,另文探讨)
FilehookVM::FilehookVM(VMHANDLE hVM) : VVirtualMachine(hVM) {}
FilehookThread::FilehookThread(THREADHANDLE hThread) : VThread(hThread) {}
BOOL FilehookDevice::OnSysDynamicDeviceInit()
{
PrevHook = IFSMgr_InstallFileSystemApiHook(MyIfsHook);//安装文件系统挂钩回调函数
//初始化数据成员
FILE=DIR=NULL;
//将目录和文件列表指针初始化为NULL,实际上,文件名和目录列表都是一个单链表,你也可以用hash表等来实现。
ENDFILE=FILE; //初始化尾指针
ENDFILE-&Next=NULL; //将尾指针的下一个元素指针初始化为NULL
ENDDIR=DIR;
ENDDIR-&Next=NULL;
for(int i=0;i&26;i++)
DRIVER[i].iIsIn=0;
//将驱动器列表初始化,此时表时没有驱动器,当加入驱动器时,只需要将相应的元素的iIsIn域置为1即可。
//以下代码打开日志文件,调用的是Ring0级的文件i/o函数,当然,此时的日志很简单,只记录了什么文件被保护,什么文件被企图删除
WORD pAction;
BYTE pError;
::logfile=R0_OpenCreateFile(true,“log.txt”,OPEN_ACCESS_WRITEONLY,ATTR_NORMAL,ACTION_IFNOTEXISTS_CREATE|ACTION_IFEXISTS_TRUNCATE,R0_NO_CACHE,&pAction,&pError);
//logfile为全局日志文件句柄
::WriteLog(logfile,“开始记录”);
return TRUE;
}
BOOL FilehookDevice::OnSysDynamicDeviceExit() //动态卸载事件响应函数
{
//删除动态分配的内存,这些内存是在前台程序加入文件或目录到保护列表时动态分配的
FT *temp;//临时指针变量
while(FILE!=NULL)//文件列表
{
temp=::FILE;
::FILE=::FILE-&Next;
delete temp;
}
while(DIR!=NULL)//目录列表
{
temp=::DIR;
::DIR=::DIR-&Next;
delete temp;
}
::WriteLog(logfile,“正常结束运行!”);//记入日志
WORD pError;
R0_CloseFile(logfile,&pError);//关闭日志文件
IFSMgr_RemoveFileSystemApiHook(MyIfsHook); //卸载文件挂钩回调用函数
return TRUE;
}
DWORD FilehookDevice::OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams)//前台控制消息响应函数
{
switch(pDIOCParams-&dioc_IOCtlCode)//检查操作类型,这些消息是在前面定义的
{
case ADD_FILE://添加文件
FT *file,*pfile;
pfile=(FT *)pDIOCParams-&dioc_InBuf;//生成一个FT类型的指针并指向传递过来的内存区域
WriteLog(logfile,“添加文件”); //记入日志,当然在正式发行时可以去掉,这里是为了调试方便
WriteLog(logfile,pfile-&PathName);//记录添加的文件名,可以和前台的对比,看有没有误传,这里也是为了调试方便
file=new FT; //分配内存
if(file!=NULL)
{
memcpy(file,pfile,sizeof(FT)); //将传递过来的内存块保存下来,以下代码是典型的链表操作
if(::FILE==NULL) //如果是列表中的第一个文件
::FILE=file;
else //接下来的文件
::ENDFILE-&Next=file;
file-&Next=NULL;
ENDFILE=file;
}
break;
case ADD_DIR://添加目录,与上面的代码类似
FT *dir,*pdir; //目录和文件实际上相似,所以用相同的结构定义
pdir=(FT *)pDIOCParams-&dioc_InBuf;
dir=new FT;
if(dir!=NULL)
{
memcpy(dir,pdir,sizeof(FT));
if(::DIR==NULL)
::DIR=dir;
else
::ENDDIR-&Next=dir;
dir-&Next=NULL;
::ENDDIR=dir;
}
break;
case ADD_DRV://添加驱动器,将相应的元素的iIsIn设为1即可;如:如果加入的是A盘,就将下标为0的元素的iIsIn设为1,依次类推。
DT * driver; //DT和FT都是结构
driver=(DT *)pDIOCParams-&dioc_InBuf; //取得传入的参数
if(driver-&iIsIn&=‘A’&&driver-&iIsIn&=‘Z’)//检查传入的参数合法性,只允许A-Z字符传入。
{
DRIVER[driver-&iIsIn-‘A’].iIsIn=1;//将相应的置1
DRIVER[driver-&iIsIn-‘A’].iProtype=driver-&iProtype;
}
break;
default:
break;
}
return 0;
}
int _cdecl MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir)
//挂钩回调函数
{
_QWORD result;//取文件名时的返回值域,详见vtoolsd的帮助
unsigned char * path; //取得的路径指针
int s;
char * action;//调试用变量,配合dout函数你可以在Driver Monitor中看到它的值
switch(fn)
{
case IFSFN_OPEN:
action=“打开文件”;
/*
path= (unsigned char*)malloc(pir-&ir_ppath-&pp_totalLength+3);
if(path!=NULL)
{
path[0]=Drive+‘A’-1;
path[1]=‘:’;
UniToBCSPath(path+2,pir-&ir_ppath-&pp_elements,pir-&ir_ppath-&pp_totalLength,BCS_OEM,&result);
strcpy(FileName,(char *)path);
free(path);
}
else
action=“分配内存失败!”;
*/
break;
case IFSFN_READ:
action=“读取文件”;
break;
case IFSFN_WRITE:
action=“写出文件”;
break;
case IFSFN_RENAME:
action=“更名文件”;
break;
case IFSFN_DELETE:
action=“删除文件”;
path= (unsigned char*)malloc(pir-&ir_ppath-&pp_totalLength+3);
if(path!=NULL)
{
path[0]=Drive+‘A’-1;
path[1]=‘:’;
UniToBCSPath(path+2,pir-&ir_ppath-&pp_elements,pir-&ir_ppath-&pp_totalLength,BCS_OEM,&result);//取得文件路径,并将用unicode表示的文件路径名转换为C语言风格的字符串,由Vtoolsd提供的例程。
strcpy(FileName,(char *)path);
for(int i=0;i&26;i++)//判断是否驱动器保护
if(DRIVER[Drive-1].iIsIn!=0)
{
WriteLog(logfile,“由于该驱动器保护,以下文件不能被删除:”);
WriteLog(logfile,FileName);
return 0;
}
FT *temp;
for(temp=FILE;temp!=NULL;temp=FILE-&Next) //判断是不是在操作受保护的文件
//注意:一般情况下的删除操作只是将文件改名放到回收站中,所以得不到保护。这里保护的只是直接按住shift键后删除的文件。如果要保护放到加收站中的文件,需要监视文件更名操作,并且首先要得知回收站文件夹的路径。
{
if(!strcmp(temp-&PathName,(const char *)path))//是的话就保护
{
WriteLog(logfile,“由于保护以下文件不能被删除!”);
WriteLog(logfile,temp-&PathName);
return 0; //直接返回就行了,这样其它的ifs hook函数就得不到动作的机会,包括操作系统的API函数。
}
}
free(path);
}
else
action=“分配内存失败!”;
break;
case IFSFN_DIR:
action=“目录操作”;
break;
}
//如果在Driver moniter中监视的话可以
return (*PrevHook)(pfn, fn, Drive, ResType, CodePage, pir);//传给下一个hook 函数
}
头文件定义:
// FILEHOOK.h - include file for VxD FILEHOOK
#include &vtoolscp.h&
#define DEVICE_CLASS FilehookDevice
#define FILEHOOK_DeviceID UNDEFINED_DEVICE_ID
#define FILEHOOK_Init_Order UNDEFINED_INIT_ORDER
#define FILEHOOK_Major 1
#define FILEHOOK_Minor 0
class FilehookDevice : public VDevice
{
public:
virtual BOOL OnSysDynamicDeviceInit();
virtual BOOL OnSysDynamicDeviceExit();
virtual DWORD OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams);
// int FilehookDevice::MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir);
};
class FilehookVM : public VVirtualMachine
{
public:
FilehookVM(VMHANDLE hVM);
};
class FilehookThread : public VThread
{
public:
FilehookThread(THREADHANDLE hThread);
};
//------------------------------------------------------------以上代码为vtoolsd自动生成代码
int _cdecl MyIfsHook(pIFSFunc pfn, int fn, int Drive, int ResType,int CodePage, pioreq pir);
//------------------------------------------------------------
ppIFSFileHookFunc PrevHook;//保存以前的钩子函数的变量
char FileName[512];
//------------------------------------------------------------
char* GetResTypeString(int restype)//读取操作的文件系统类型
{
switch (restype)
{
case IFSFH_RES_UNC:
return “IFSFH_RES_UNC”;
case IFSFH_RES_NETWORK:
return “IFSFH_RES_NETWORK”;
case IFSFH_RES_LOCAL:
return “IFSFH_RES_LOCAL”;
case IFSFH_RES_CFSD:
return “IFSFH_RES_CFSD”;
case IFSFH_RES_NETWORK + IFSFH_RES_UNC:
return “IFSFH_RES_NETWORK (UNC)”;
case IFSFH_RES_LOCAL + IFSFH_RES_UNC:
return “IFSFH_RES_LOCAL (UNC)”;
case IFSFH_RES_CFSD + IFSFH_RES_UNC:
return “IFSFH_RES_CFSD (UNC)”;
default:
return “Unknown”;
}
}
//-----------------------------------------------------------
void WriteLog(HANDLE logfile,char * log) //日志记载函数
{
WORD pError;
static int logoffset=0;//记录日志文件的偏移量,R0级的文件函数实际上是文件中断调用的简单封装。
char temp[512];
strcpy(temp,log);
temp[strlen(log)]=‘\r’;
temp[strlen(log)+1]=‘\n’;
temp[strlen(log)+2]=‘\0’;
R0_WriteFile(true,logfile,temp,strlen(temp),logoffset,&pError);//调用ring0级写文件函数
logoffset+=strlen(temp);
}
//-----------------------------------------------------------
typedef struct File_Type //FT文件类型定义
{
short int Driver;
char PathName[512];
struct File_Type * Next;
short int iProType;//保护类型
} FT;//文件项
FT * DIR,* ENDDIR;//保护目录列表头指针
FT * FILE,* ENDFILE;//保护文件列表头指针
typedef struct Driver_Type //驱动器类型定义
{
short int iIsIn;
short int iProtype;//保护类型
} DT;
DT DRIVER[26];//要保护的驱动器
HANDLE logfile;
重要提示:
在作文件读、写操作时请不要再作取文件名的操作,此时由于这些操作的连续性,将导致使机重资源急剧消耗,大部分情况下将导致蓝屏死机。
//------------------------------------------------------
以下为前台程序
在程序中添加三个对话框,分别添加目录,添加文件名,添加驱动器。
目录添加对话框的头文件(类定义部分)
//--------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// CAddDir dialog
class CAddDir : public CDialog
{
// Construction
public:
CAddDir(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAddDir)
enum { IDD = IDD_DIALOG2 };
CString m_dir;//添加一个数据成员,和一个编辑框关联
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAddDir)
public:
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAddDir)
afx_msg void OnButton1();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
ADDDIR的实现文件
//------------------------------------------------------------
void CAddDir::OnButton1() //编辑框边上的目录浏览按钮的实现代码
{
// TODO: Add your control notification handler code here
BROWSEINFO FileInfo; 目录浏览函数需要的结构,详见 win32 API参考手册
char Dir[256]; //放置目录名的变量
LPITEMIDLIST Item;
FileInfo.hwndOwner=m_hWnd;
FileInfo.pidlRoot=NULL;
FileInfo.pszDisplayName=NULL;
FileInfo.lpszTitle=“请选择文件夹”; //对话框标题
FileInfo.ulFlags=0;
FileInfo.lpfn=NULL;
FileInfo.lParam=0;
FileInfo.iImage=0;
Item=SHBrowseForFolder(&FileInfo);//显示对话框
SHGetPathFromIDList(Item,Dir);//取得目录名
m_dir=Dir;//赋给编辑框关联的变量
UpdateData(false); //更新编辑框的显示
}
//-----------------------------------------------------------
void CAddDir::OnOK() //确定按钮
{
// TODO: Add extra validation here
struct File_Type //文件结构,放置目录,为了简化起见,FT的iIsIn域在这时放置驱动器盘符
{
short int Driver;
char PathName[512];
struct File_Type * Next;
short int iProType;//保护类型
} FT;
if(!m_dir.IsEmpty())//如果非空的话,则作以下操作
{
FT.iProType=PDELETE;//保护类型,”防删”
FT.Driver=toupper(LPCTSTR(m_dir)[0]); //将盘符转成大写
m_dir.MakeUpper();
strcpy(FT.PathName,LPCTSTR(m_dir));
CFpApp * myapp=(CFpApp *)AfxGetApp();
DeviceIoControl(myapp-&hcVxd,ADD_DIR,&FT,sizeof(FT),0,0,0,0);
}
CDialog::OnOK();
}
//------------------------------------------------------------
ADDDRV的头文件
//-------------------------------------------------------------
class CAddDrv : public CDialog
{
// Construction
public:
CAddDrv(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAddDrv)
enum { IDD = IDD_DIALOG3 };
//}}AFX_DATA
CComboBox * m_Driver;//添加一个CcomboBox类型号的指针变量,以后将指向我们在对话框上加入的下拉列表框。
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAddDrv)
public:
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAddDrv)
virtual BOOL OnInitDialog();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//---------------------------------------------------------------------
ADDDRV实现文件
//----------------------------------------------------------------------
BOOL CAddDrv::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
m_Driver=(CComboBox *)GetDlgItem(IDC_COMBO_DRV);//取得列表框的指针
for(int drive = 1; drive &= 26; drive++ )//测试哪个驱动器可用
if( !_chdrive( drive ) )
{
char Vdrive[3];
Vdrive[1]=‘:’;
Vdrive[0]=drive+‘A’-1;
Vdrive[2]=‘\0’;
m_Driver-&AddString(Vdrive);//如果可用就把它加入列表框中
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAddDrv::OnOK()
{
// TODO: Add extra validation here
struct Driver_Type
{
short int iIsIn;
short int iProtype;//保护类型
} DT;
m_Driver=(CComboBox )GetDlgItem(IDC_COMBO_DRV);
if(m_Driver-&GetCurSel()!=CB_ERR)
{
char temp[3];
m_Driver-&GetLBText(m_Driver-&GetCurSel(),temp);//这里的iIsIn存放驱动器符,主要是为了简化定义
//AfxMessageBox(temp); //测试代码
DT.iIsIn=temp[0];
DT.iProtype=PWRITE;
CFpApp * myapp=(CFpApp)AfxGetApp();
DeviceIoControl(myapp-&hcVxd,ADD_DRV,&DT,sizeof(DT),0,0,0,0); //将驱动器信息传给VXD驱动程序,它的句柄是在框加窗口中打开的,且定义为全局变量
//AfxMessageBox(temp);
}
CDialog::OnOK();
}
//--------------------------------------------------------
主框架窗口的实现文件中改动部分
//--------------------------------------------------------
void CMainFrame::ActivateFrame(int nCmdShow)
{
// TODO: Add your specialized code here and/or call the base class
AfxGetMainWnd()-&SetWindowText(_T(“文件保护专家1.0”));//改变窗口标题
CFrameWnd::ActivateFrame(nCmdShow);
}
void CMainFrame::OnHelp() //帮助菜单的实现
{
// TODO: Add your command handler code here
AfxMessageBox(“什么?GPL版本也要帮助?看看源程序,帮助就DIY了吧!\n以后正式版本会提供!”,MB_SYSTEMMODAL+MB_ICONQUESTION);
}
void CMainFrame::OnSetfile() //显示添加文件对话框
{
// TODO: Add your command handler code here
CAddFile myaddfile;
myaddfile.DoModal();
}
void CMainFrame::OnSetdir() //显示目录添加对话框
{
// TODO: Add your command handler code here
CAddDir MyAddDir;
MyAddDir.DoModal();
}
void CMainFrame::OnSetdriver() //显示添加驱动器对话框
{
// TODO: Add your command handler code here
CAddDrv MyAddDrv;
MyAddDrv.DoModal();
}
void CMainFrame::OnHidewindow() //隐藏主窗口菜单的实现,主要是进程的隐藏
{
// TODO: Add your command handler code here
AfxMessageBox(“唤醒热键为: Ctrl+Shift+Q”);
CWnd::ShowWindow(SW_HIDE);//隐藏窗口
//以下代码隐藏当前进程
typedef DWORD (WINAPI Fun) (DWORD,DWORD); //定义回调函数原型
HINSTANCE hKernel=LoadLibrary(“Kernel32.dll”);
if ( hKernel != NULL)
{
Fun * RegisterServiceProcess=(Fun *)/
GetProcAddress(hKernel,“RegisterServiceProcess”);
( *RegisterServiceProcess)(NULL,1);
FreeLibrary(hKernel);
}
}
//------------------------------------------------
ADDFILE的实现文件
//-------------------------------------------------
void CAddFile::OnButton1() 编辑框边上的浏览按钮,调用标准对话框
{
// TODO: Add your control notification handler code here
CFileDialog MyFile(true,“.“,”.*”);
MyFile.DoModal();
m_filename=MyFile.GetPathName();
UpdateData(false);
}
void CAddFile::OnOK()
{
// TODO: Add extra validation here
struct File_Type
{
short int Driver;
char PathName[512];
struct File_Type * Next;
short int iProType;//保护类型
} FT;
if(!m_filename.IsEmpty())//判断是否为空
{
FT.iProType=PDELETE;
FT.Driver=toupper(LPCTSTR(m_filename)[0]);
m_filename.MakeUpper();
strcpy(FT.PathName,LPCTSTR(m_filename));
CFpApp * myapp=(CFpApp )AfxGetApp();
DeviceIoControl(myapp-&hcVxd,ADD_FILE,&FT,sizeof(FT),0,0,0,0);
//AfxMessageBox(temp);
}
CDialog::OnOK();
}
//-----------------------------------------------------
ADDFILE的头文件
//------------------------------------------------------
class CAddFile : public CDialog
{
// Construction
public:
CAddFile(CWnd pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CAddFile)
enum { IDD = IDD_DIALOG1 };
CString m_filename;//和编辑框关联的变量,保存文件名和路径
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAddFile)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CAddFile)
afx_msg void OnButton1();
virtual void OnOK();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
//----------------------------------------------------
视图类的实现文件
//----------------------------------------------------
// fpView.cpp : implementation of the CFpView class
//
#include “stdafx.h”
#include “fp.h”
#include “fpDoc.h”
#include “fpView.h”
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE = FILE;
#endif
/////////////////////////////////////////////////////////////////////////////
// CFpView
IMPLEMENT_DYNCREATE(CFpView, CView)
BEGIN_MESSAGE_MAP(CFpView, CView)
//{{AFX_MSG_MAP(CFpView)
ON_WM_CREATE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
ON_MESSAGE(WM_HOTKEY,OnHotKey)//加入热键响应函数
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFpView construction/destruction
CFpView::CFpView()
{
// TODO: add construction code here
}
CFpView::~CFpView()
{
}
BOOL CFpView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CFpView drawing
void CFpView::OnDraw(CDC* pDC)
{
CFpDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CFpView printing
BOOL CFpView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CFpView::OnBeginPrinting(CDC* /pDC/, CPrintInfo* /pInfo/)
{
// TODO: add extra initialization before printing
}
void CFpView::OnEndPrinting(CDC* /pDC/, CPrintInfo* /pInfo/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CFpView diagnostics
#ifdef _DEBUG
void CFpView::AssertValid() const
{
CView::AssertValid();
}
void CFpView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CFpDoc* CFpView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument-&IsKindOf(RUNTIME_CLASS(CFpDoc)));
return (CFpDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CFpView message handlers
int CFpView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CFpApp * myapp=(CFpApp*)AfxGetApp();
myapp-&hcVxd=CreateFile(“\\.\Filehook.vxd”,0,0,0,CREATE_NEW,FILE_FLAG_DELETE_ON_CLOSE,0);//加载vxd驱动
if(myapp-&hcVxd==INVALID_HANDLE_VALUE)//如果失败就退出程序
{
AfxMessageBox(“加载VXD失败,程序将退出!”);
::ExitProcess(0);
}
//注册热键 ctrl+shit+Q
RegisterHotKey(m_hWnd,1001,MOD_CONTROL|MOD_SHIFT,‘Q’);
RegisterHotKey(m_hWnd,1002,MOD_CONTROL|MOD_SHIFT,‘q’);
return 0;
}
void CFpView::OnDestroy()
{
CView::OnDestroy();
::UnregisterHotKey(m_hWnd,1001); //删除热键
::UnregisterHotKey(m_hWnd,1002);
CFpApp * myapp=(CFpApp*)AfxGetApp();
CloseHandle(myapp-&hcVxd); //释放vxd驱动
// TODO: Add your message handler code here
}
LRESULT CFpView::OnHotKey(WPARAM wParam,LPARAM lParam)
{
if(wParam==1001||wParam==1002)//响应热键,显示主窗口
{
AfxGetMainWnd()-&ShowWindow(SW_SHOW);
}
return 0;
}
//-------------------------------------------------------------------
主程序文件中的定义
//-------------------------------------------------------------------
/ fp.h : main header file for the FP application
//
#if !defined(AFX_FP_H__33040F78_DC9C_11D4_9C4E_006008D4550A__INCLUDED_)
#define AFX_FP_H__33040F78_DC9C_11D4_9C4E_006008D4550A__INCLUDED_
#if _MSC_VER & 1000
#pragma once
#endif // _MSC_VER & 1000
#ifndef AFXWIN_H
#error include ‘stdafx.h’ before including this file for PCH
#endif
#include “resource.h” // main symbols
/////////////////////////////////////////////////////////////////////////////
// CFpApp:
// See fp.cpp for the implementation of this class
//
#if !defined(MM)
#define MM
#define REMOVE_DRV 100
#define REMOVE_FILE 101
#define REMOVE_DIR 102//删除元素
#define ADD_DIR 103//添加元素
#define ADD_DRV 104//添加驱动
#define ADD_FILE 105//删除文件
#define STARTP 106 //启动保护
#define STOPP 107 //停止保护
#define PREAD 10//读保护
#define PDELETE 11//删除保护
#define PWRITE 12//写保护
#define PALL 13//所有保护
#define PCREATE 14//禁止创建文件
#define PASSHWND 10000;
#endif
//--------------------------------------------------------------------
class CFpApp : public CWinApp
{
public:
CFpApp();
HANDLE hcVxd;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CFpApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// Implementation
//{{AFX_MSG(CFpApp)
afx_msg void OnAppAbout();
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_FP_H__33040F78_DC9C_11D4_9C4E_006008D4550A__INCLUDED_)
//-------------------------------------------------------------------
以上是前台程序的实现,只列出了改动过的部分,完整的程序请看源程序包。