利用Windows外殼擴充保護檔案夾

來源:互聯網
上載者:User

 在Win32作業系統(包括Win9X、Windows NT、Windows 2000)不但有方便的圖形使用者(GUI)介面,微軟還為windows使用者介面保留了強大的可擴充性。其中對於Windows介面的作業環境(這裡稱為外殼Shell),微軟提供了一種稱為外殼擴充(Shell Extensions)的功能來實現檔案系統操作的可程式化性。如果你的機器中安裝了Word 7.0以上的版本,當你滑鼠右鍵單擊一個DOC檔案,在快顯功能表中選“屬性”項,在屬性頁面中不僅顯示顯示檔案的大小、建立日期等資訊,同時還增加了Doc文檔的摘要、統計等資訊;又例如安裝了winZip 6.0以上版本後,當選中一個或多個檔案或檔案夾後在單擊滑鼠右鍵,在彈出的右鍵菜單中就增加了“Add To Zip”等一個zip檔案壓縮選項。上面的這些功能都是通過Windows外殼擴充來實現的。
Windows外殼擴充是這樣實現的。首先要編寫外殼擴充程式,一個外殼擴充程式是基於COM(Component Object Model)組件模型的。外殼是通過介面(Interface)來訪問對象的。外殼擴充被設計成32位的進程中伺服器程式,並且都是以動態連結程式庫的形式為作業系統提供服務的。
寫好外殼擴充程式後,必須將它們註冊才會生效。所有的外殼擴充都必須在Windows註冊表的HKEY_CLASSES_ROOT/CLSID鍵之下進行註冊。在該鍵下面可以找到許多名字像{ACDE002F-0000-0000-C000-000000000046}的鍵,這類鍵就是全域唯一類別識別項。每一個外殼擴充都必須有一個全域唯一類別識別項,Windows正是通過此唯一類別識別項來找到外殼延伸模組處理常式的。在類別識別項之下的InProcServer32子鍵下記錄著外殼擴充動態連結程式庫在系統中的位置。

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外殼擴充程式。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.