现在的位置: 首页 > 综合 > 正文

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

2013年10月16日 ⁄ 综合 ⁄ 共 5611字 ⁄ 字号 评论关闭
利用Windows外壳扩展保护文件夹  
   
  Windows系统支持以下7类的外壳扩展功能:  
  (1)Context   menu   handlers向特定类型的文件对象增添上下文相关菜单;    
  (2)Drag-and-drop   handlers用来支持当用户对某种类型的文件对象进行拖放操作时的OLE数据传输;    
  (3)Icon   handlers用来向某个文件对象提供一个特有的图标,也可以给某一类文件对象指定图标;    
  (4)Property   sheet   handlers给文件对象增添属性页,属性页可以为同一类文件对象所共有,也可以给一个文件对象指定特有的属性页;    
  (5)Copy-hook   handlers在文件夹对象或者打印机对象被拷贝、移动、删除和重命名时,就会被系统调用,通过为Windows增加Copy-hook   handlers,可以允许或者禁止其中的某些操作;    
  (6)Drop   target   handlers在一个对象被拖放到另一个对象上时,就会被系统被调用;    
  (7)Data   object   handlers在文件被拖放、拷贝或者粘贴时,就会被系统被调用。  
  本文介绍的文件夹保护功能就是通过上面的第5类,既Copy-hook   handlers来实现的。一个支持Copy-hook   handlers的程序除了上面提到的要在注册表的HKEY_CLASSES_ROOT/CLSID下注册之外,还需要在HKEY_CLASSES_ROOT/Directory/shellex/CopyHookHandlers/下注册服务器程序的类。  
  由于Windows外壳服务器程序是基于COM组件模型的,所以编写外壳程序就是构造一个COM对象的过程,由于Delphi4.0以上的版本支持Windows外壳扩展和COM组件模型,所以可以利用Delphi来编写外壳扩展程序。  
  利用Delphi编写Copy-hook   handle需要实现ICopyHook接口。ICopyHook是一个十分简单的接口,要实现的只有CopyCallBack方法。ICopyHook的CopyCallBack方法的定义如下:  
  UINT   CopyCallback(  
          HWND   hwnd,   file://Handle/   of   the   parent   window   for   displaying   UI   objects  
          UINT   wFunc,   file://Operation/   to   perform.  
          UINT   wFlags,   file://Flags/   that   control   the   operation  
          LPCSTR   pszSrcFile,   file://Pointer/   to   the   source   file  
          DWORD   dwSrcAttribs,   file://Source/   file   attributes  
          LPCSTR   pszDestFile,   file://Pointer/   to   the   destination   file  
          DWORD   dwDestAttribs   file://Destination/   file   attributes  
        );  
  其中的参数hwnd是一个窗口句柄,Copy-hook   handle以此为父窗口。参数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的组合。  
   
    参数wFlags指定操作的标志;参数pszSrcFile和pszDestFile指定源文件夹和目标文件夹。参数dwSrcAttribs和dwDesAttribs指定源文件夹和目标文件夹的属性。函数返回值可以为IDYES、IDNO和IDCANCEL。分别指示Windows外壳允许操作、阻止操作,但是其他操作继续、阻止当前操作,取消为执行的操作。  
    下面是具体的程序实现:  
    首先在Delphi的菜单中选   File|New选项,选择其中的DLL图标,按Ok键建立一个DLL工程文件,在其中添加以下代码:  
  library   CopyHook;  
   
  uses  
      ComServ,  
      CopyMain   in   'CopyMain.pas';  
   
  exports  
      DllGetClassObject,  
      DllCanUnloadNow,  
      DllRegisterServer,  
      DllUnregisterServer;  
   
  {$R   *.TLB}  
   
  {$R   *.RES}  
   
  begin  
  end.  
  将文件保存为   CopyHook.dpr。再在Delphi菜单中选File|New选项,选择其中的Unit图标,按Ok键建立一个Pas文件,在其中加入以下代码:  
  unit   CopyMain;  
   
  interface  
   
  uses   Windows,   ComObj,   ShlObj;  
   
  type  
      TCopyHook   =   class(TComObject,   ICopyHook)  
      protected  
          function   CopyCallback(Wnd:   HWND;   wFunc,   wFlags:   UINT;   pszSrcFile:   PAnsiChar;  
              dwSrcAttribs:   DWORD;   pszDestFile:   PAnsiChar;   dwDestAttribs:   DWORD):   UINT;   stdcall;  
      end;  
   
      TCopyHookFactory   =   class(TComObjectFactory)  
      protected  
          function   GetProgID:   string;   override;  
          procedure   ApproveShellExtension(Register:   Boolean;   const   ClsID:   string);  
              virtual;  
      public  
          procedure   UpdateRegistry(Register:   Boolean);   override;  
      end;  
   
  implementation  
   
  uses   ComServ,   SysUtils,   Registry;  
   
  {   TCopyHook   }  
   
  file://当/Windows外壳程序执行文件夹或者打印机端口操作时,CopyCallBack  
  file://方/法就会被调用。  
  function   TCopyHook.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  
      Case   wFunc   of  
          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   }  
   
  function   TCopyHookFactory.GetProgID:   string;  
  begin  
      Result   :=   '';  
  end;  
   
  procedure   TCopyHookFactory.UpdateRegistry(Register:   Boolean);  
  var  
      ClsID:   string;  
  begin  
      ClsID   :=   GUIDToString(ClassID);  
      inherited   UpdateRegistry(Register);  
      ApproveShellExtension(Register,   ClsID);  
      if   Register   then  
          file://将/clsid   加入到注册表的CopyHookHandlers中  
          CreateRegKey('directory/shellex/CopyHookHandlers/'   +   ClassName,   '',  
              ClsID)  
      else  
          DeleteRegKey('directory/shellex/CopyHookHandlers/'   +   ClassName);  
  end;  
   
  procedure   TCopyHookFactory.ApproveShellExtension(Register:   Boolean;  
      const   ClsID:   string);  
  const  
      SApproveKey   =   'SOFTWARE/Microsoft/Windows/CurrentVersion/Shell   Extensions/Approved';  
  begin  
      with   TRegistry.Create   do  
          try  
              RootKey   :=   HKEY_LOCAL_MACHINE;  
              if   not   OpenKey(SApproveKey,   True)   then   Exit;  
              if   Register   then   WriteString(ClsID,   Description)  
              else   DeleteValue(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子目录,然后在其中输入Regsvr32   x:/xxx/xxx/copyhook.dll   ,其中x:/xxx/xxx/是编译的CopyHook.dll所在的全路径名。也可以在Run菜单中选择Register   ActiveX   Server来注册。  
  当文件注册成功之后,在Windows的Explore中任意改变一个文件夹的名字或者移动一个目录,就会有一个提示框弹出,提示用户是否确定执行操作。如图所示:  
   
     
   
    按“是”将执行文件夹操作,按“否”或者“取消”将取消相应的文件夹操作。  
    上面介绍的只是Delphi实现Windows外壳扩展的一种,参照上面的程序和Delphi关于Windows的COM组件模型的编程,就可以编写出十分专业化的Windows外壳扩展程序。   
   

抱歉!评论已关闭.