利用Windows外壳扩展保护文件夹

     在Win32操作系统(包括Win9X、WindowsNT、Windows2000)不但有方便的图形用户(GUI)界面,微软还为Windows用户界面保留了强大的可扩充性。其中对于Windows界面的操作环境(这里称为外壳Shell),微软提供了一种称为外壳扩展(ShellExtensions)的功能来实现文件系统操作的可编程性。如果你的机器中安装了Word7.0以上的版本,当你鼠标右键单击一个DOC文件,在弹出菜单中选“属性”项,在属性页中不仅显示显示文件的大小、建立日期等信息,同时还增加了Doc文档的摘要、统计等信息;又例如安装了winZip6.0以上版本后,当选中一个或多个文件或文件夹后在单击鼠标右键,在弹出的右键菜单中就增加了“AddToZip”等一个zip文件压缩选项。上面的这些功能都是通过Windows外壳扩展来实现的。


     Windows外壳扩展是这样实现的。首先要编写外壳扩展程序,一个外壳扩展程序是基于COM(ComponentObjectModel)组件模型的。外壳是通过接口(Interface)来访问对象的。外壳扩展被设计成32位的进程中服务器程序,并且都是以动态链接库的形式为操作系统提供服务的。


     写好外壳扩展程序后,必须将它们注册才能生效。所有的外壳扩展都必须在Windows注册表的HKEY_CLASSES_ROOT\CLSID键之下进行注册。在该键下面可以找到许多名字像{ACDE002F-0000-0000-C000-000000000046}的键,这类键就是全局唯一类标识符。每一个外壳扩展都必须有一个全局唯一类标识符,Windows正是通过此唯一类标识符来找到外壳扩展处理程序的。在类标识符之下的InProcServer32子键下记录着外壳扩展动态链接库在系统中的位置。

Windows系统支持以下7类的外壳扩展功能:

   (1)Contextmenuhandlers向特定类型的文件对象增添上下文相关菜单;
   (2)Drag-and-drophandlers用来支持当用户对某种类型的文件对象进行拖放操作时的OLE数据传输;
   (3)Iconhandlers用来向某个文件对象提供一个特有的图标,也可以给某一类文件对象指定图标;
   (4)Propertysheethandlers给文件对象增添属性页,属性页可以为同一类文件对象所共有,也可以给一个文件对象指定特有的属性页;
   (5)Copy-hookhandlers在文件夹对象或者打印机对象被拷贝、移动、删除和重命名时,就会被系统调用,通过为Windows增加Copy-hookhandlers,可以允许或者禁止其中的某些操作;
   (6)Droptargethandlers在一个对象被拖放到另一个对象上时,就会被系统被调用;
   (7)Dataobjecthandlers在文件被拖放、拷贝或者粘贴时,就会被系统被调用。


    本文介绍的文件夹保护功能就是通过上面的第5类,既Copy-hookhandlers来实现的。一个支持Copy-hookhandlers的程序除了上面提到的要在注册表的HKEY_CLASSES_ROOT\CLSID下注册之外,还需要在HKEY_CLASSES_ROOT\Directory\shellex\CopyHookHandlers\下注册服务器程序的类。


     由于Windows外壳服务器程序是基于COM组件模型的,所以编写外壳程序就是构造一个COM对象的过程,由于Delphi4.0以上的版本支持Windows外壳扩展和COM组件模型,所以可以利用Delphi来编写外壳扩展程序。
利用Delphi编写Copy-hookhandle需要实现ICopyHook接口。ICopyHook是一个十分简单的接口,要实现的只有CopyCallBack方法。ICopyHook的CopyCallBack方法的定义如下:
UINTCopyCallback(
HWNDhwnd, file://HandleoftheparentwindowfordisplayingUIobjects
UINTwFunc, file://Operationtoperform.
UINTwFlags, file://Flagsthatcontroltheoperation
LPCSTRpszSrcFile, file://Pointertothesourcefile
DWORDdwSrcAttribs, file://Sourcefileattributes
LPCSTRpszDestFile, file://Pointertothedestinationfile
DWORDdwDestAttribs file://Destinationfileattributes
);
其中的参数hwnd是一个窗口句柄,Copy-hookhandle以此为父窗口。参数wFunc指定要被执行的操作,其取值为下表中所列之一:

常量 取值 含义
FO_COPY $2 复制由pszSrcFile指定的文件到由pszDestFile指定的位置。
FO_DELETE $3 删除由pszSrcFile指定的文件。
FO_MOVE $1 移动由pszSrcFile指定的文件到由pszDestFile指定的位置。
FO_RENAME $4 重命名由pszSrcFile指定的文件到由pszDestFile指定的文件名。
PO_DELETE $13 删除pszSrcFile指定的打印机。
PO_PORTCHANGE $20 改变打印机端口。PszSrcFile和pszDestFile为两个以Null结尾的字符串,分别指定当前和新的打印机端口名。
PO_RENAME $14 重命名由pszSrcFile指定的打印机端口。
PO_REN_PORT $34 PO_RENAME和PO_PORTCHANGE的组合。 http://www.mscto.com

参数wFlags指定操作的标志;参数pszSrcFile和pszDestFile指定源文件夹和目标文件夹。参数dwSrcAttribs和dwDesAttribs指定源文件夹和目标文件夹的属性。函数返回值可以为IDYES、IDNO和IDCANCEL。分别指示Windows外壳允许操作、阻止操作,但是其他操作继续、阻止当前操作,取消为执行的操作。
下面是具体的程序实现:
首先在Delphi的菜单中选File|New选项,选择其中的DLL图标,按Ok键建立一个DLL工程文件,在其中添加以下代码:


libraryCopyHook;

uses
ComServ,
CopyMainin'CopyMain.pas'; http://www.mscto.com

exports
DllGetClassObject,
DllCanUnloadNow,
DllReGISterServer,
DllUnregisterServer;

{$R*.TLB}

{$R*.RES}

begin
end.


将文件保存为CopyHook.dpr。再在Delphi菜单中选File|New选项,选择其中的Unit图标,按Ok键建立一个Pas文件,在其中加入以下代码:


unitCopyMain;

interface

usesWindows,ComObj,ShlObj;

type
TCopyHook=class(TComObject,ICopyHook)
protected
functionCopyCallback(Wnd:HWND;wFunc,wFlags:UINT;pszSrcFile:PAnsiChar;
dwSrcAttribs:DWORD;pszDestFile:PAnsiChar;dwDestAttribs:DWORD):UINT;stdcall;
end;

TCopyHookFactory=class(TComObjectFactory)
protected
functionGetProgID:string;override;
procedureApproveShellExtension(Register:Boolean;constClsID:string);
virtual;
public
procedureUpdateRegistry(Register:Boolean);override;
end;

implementation

usesComServ,SysUtils,Registry; 软件开发网

{TCopyHook}

file://当Windows外壳程序执行文件夹或者打印机端口操作时,CopyCallBack
file://方法就会被调用。
functionTCopyHook.CopyCallback(Wnd:HWND;wFunc,wFlags:UINT;
pszSrcFile:PAnsiChar;dwSrcAttribs:DWORD;pszDestFile:PAnsiChar;
dwDestAttribs:DWORD):UINT;
const
FO_COPY=2;
FO_DELETE=3;
FO_MOVE=1;
FO_RENAME=4;
var
sOp:string;
begin
CasewFuncof
FO_COPY: sOp:=format('你确定要将%s拷贝到%s吗?',[pszSrcFile,pszDestFile]);
FO_DELETE: sOp:=format('你确定要将%s删除吗?',[pszSrcFile]);
FO_MOVE: sOp:=format('你确定要将%s转移到%s吗?',[pszSrcFile,pszDestFile]);
FO_RENAME: sOp:=format('你确定要将%s重命名为%s吗?',[pszSrcFile,pszDestFile]);
else
sOp:=format('无法识别的操作代码%d',[wFlags]);
end;
//提示,让用户决定是否执行操作
Result:=MessageBox(Wnd, PChar(sOp),
'文件挂钩演示',MB_YESNOCANCEL);
end;

{TCopyHookFactory}

functionTCopyHookFactory.GetProgID:string;
begin
Result:='';
end;

procedureTCopyHookFactory.UpdateRegistry(Register:Boolean);
var
ClsID:string;
begin
ClsID:=GUIDToString(ClassID);

inherited UpdateRegistry(Register);
ApproveShellExtension(Register,ClsID);
ifRegisterthen
file://将clsid加入到注册表的CopyHookHandlers中
CreateRegKey('directory\shellex\CopyHookHandlers\' ClassName,'',
ClsID)
else
DeleteRegKey('directory\shellex\CopyHookHandlers\' ClassName);
end;

procedureTCopyHookFactory.ApproveShellExtension(Register:Boolean;
constClsID:string);
const
SAPproveKey='SOFTWARE\Microsoft\Windows\CurrentVersion\ShellExtensions\Approved';
begin
withTRegistry.Createdo
try
RootKey:=HKEY_LOCAL_MACHINE;
ifnotOpenKey(SApproveKey,True)thenExit;
ifRegisterthenWriteString(ClsID,Description)
elseDeleteValue(ClsID);
finally
Free;
end;
end;

const
CLSID_CopyHook:TGUID='{66CD5F60-A044-11D0-A9BF-00A024E3867F}';
LIBID_CopyHook:TGUID='{D2F531A0-0861-11D2-AE5C-74640BC10000}';

initialization
TCopyHookFactory.Create(ComServer,TCopyHook,CLSID_CopyHook,
'CR_CopyHook','文件操作挂钩演示',ciMultiInstance,tmApartment);
end.
将文件保存为CopyMain.Pas文件,然后编译程序为CopyHook.Dll文件,然后注册CopyHook.Dll文件,你可以使用Windows提供的RegSvr32.exe来注册,注册的方法是在Dos窗口中进入Windows的System子目录,然后在其中输入Regsvr32x:\xxx\xxx\copyhook.dll,其中x:\xxx\xxx\是编译的CopyHook.dll所在的全路径名。也可以在Run菜单中选择RegisterActiveXServer来注册。
当文件注册成功之后,在Windows的Explore中任意改变一个文件夹的名字或者移动一个目录,就会有一个提示框弹出,提示用户是否确定执行操作。如图所示:

按“是”将执行文件夹操作,按“否”或者“取消”将取消相应的文件夹操作。
上面介绍的只是Delphi实现Windows外壳扩展的一种,参照上面的程序和Delphi关于Windows的COM组件模型的编程,就可以编写出十分专业化的Windows外壳扩展程序。


 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值