Windows檔案系統過濾驅動開發教程(2)

來源:互聯網
上載者:User
Windows檔案系統過濾驅動開發教程 2.hello world,驅動對象與裝置對象

這裡所說的驅動對象是一種資料結構,在DDK中名為DRIVER_OBJECT。任何驅動程式都對應一個DRIVER_OBJECT.如何獲得本人所寫的 驅動對應的DRIVER_OBJECT呢?驅動程式的入口函數為DriverEntry,因此,當你寫一個驅動的開始,你會寫下如下的代碼:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
{
}

這個函數就相當與喜歡c語言的你所常用的main().IN是無意義的宏,僅僅表明後邊的參數是一種輸入,而對應的OUT則代表這個參數是一種返回。這裡沒有使用引用,因此如果想在參數中返回結果,一律傳入指標。

DriverObject就是你所寫的驅動對應的DRIVER_OBJECT,是系統在載入你的驅動時候所分配的。RegisteryPath是專用於你記錄你的驅動相關參數的註冊表路徑。

DriverObject重要之處,在於它擁有一組函數指標,稱為dispatch functions.

開發驅動的主要任務就是親手撰寫這些dispatch functions.當系統用到你的驅動,會向你的DO發送IRP(這是windows所有驅動的共同工作方式)。你的任務是在dispatch function中處理這些請求。你可以讓irp失敗,也可以成功返回,也可以修改這些irp,甚至可以自己發出irp。

裝置對象則是指DEVICE_OBJECT.下邊簡稱DO.

但是實際上每個irp都是針對DO發出的。只有針對由該驅動所產生的DO的IRP,
才會發給該驅動來處理。

當一個應用程式開啟檔案並讀寫檔案的時候,windows系統將這些請求變成irp發送給檔案系統驅動。

檔案系統過濾驅動將可以過濾這些irp.這樣,你就擁有了捕獲和改變檔案系統操作的能力。

象Fat32,NTFS這樣的檔案系統(File System,簡稱FS),可能產生好幾種裝置。首先檔案系統驅動本身往往產生一個控制裝置(CDO).這個裝置的主要任務是修改整個驅動的內部配置。因此一個Driver只對應一個CDO.

另一種裝置是被這個檔案系統Mount的Volume。一個FS可能有多個Volume,也可能一個都沒有。解釋一下,如果你有C:,D:,E:,F:四個分區。C:,D:為NTFS,E:,F:為Fat32.那麼C:,D:則是Fat的兩個Volume裝置對象.

實際上"C:"是該裝置的符號串連(Symbolic Link)名。而不是真正的裝置名稱。可以開啟Symbolic Links Viewer,能看到:

C: \Device\HarddiskVolume1

因此該裝置的裝置名稱為“\Device\HarddiskVolume1”.

這裡也看出來,檔案系統驅動是針對每個Volume來產生一個DeviceObject,而不是針對每個檔案的。實際上對檔案的讀寫的irp,都發到Volume裝置對象上去了。並不會產生一個“檔案裝置對象”。

掌握了這些概念的話,我們現在用簡單的代碼來產生我們的CDO,作為我們開發檔案系統驅動的第一步牛刀小試。

我不喜歡用微軟風格的代碼。太長而且難看。我對大部分資料結構和函數進行了重定義。為此我寫了一個名為wdf.h的標頭檔協助我轉換。有興趣的讀者可以發郵件向索取這個檔案。沒有也沒有關係,我總是會寫出wd_xxx系列的東西在DDK中的原形。

// -----------------wdf_filter.c中的內容-------------------------

#include "wdf.h"

wd_stat wdff_cdo_create(in wd_drv *driver,
in wd_size exten_len,
in wd_ustr *name,
out wd_dev **device)
{
return wd_dev_create(
driver,
exten_len,
name,
wd_dev_disk_fs,
wdf_dev_secure_open,
wd_false,
device);
}

wd_stat wd_main(in wd_drv* driver,
in wd_ustr* reg_path)
{
wd_ustr name;
wd_stat status = wd_stat_suc;

// 然後我產生控制裝置,雖然現在我的控制裝置什麼都不幹
wd_ustr_init(&name,L"\\FileSystem\\Filters\\our_fs_filter");
status = wdff_cdo_create(driver,0,&name,&g_cdo);

if(!wd_suc(status))
{
if(status == wd_stat_path_not_found)
{
// 這種情況發生於\FileSystem\Filters路徑不存在。這個路徑是
// 在xp上才加上的。所以2000下會運行到這裡
wd_ustr_init(&name,L"\\FileSystem\\our_fs_filter");
status = wdff_cdo_create(driver,0,&name,&g_cdo);
};
if(!wd_suc(status))
{
wd_printf0("error: create cdo failed.\r\n");
return status;
}
}

wd_printf0("success: create cdo ok.\r\n");
return status;
}

為了讓代碼看起來象上邊的那樣,我不得不做了很多轉換。如

#define DriverEntry wd_main

一種爽的感覺,終於可以在寫看起來更象是main()的函數中工作了。 wd_dev_create 這個函數內部調用的是IoCreateDevice.而wd_suc實際上是SUCCESS()這樣的宏。

// ----------------------wdf.h中的內容------------------------------
#include "ntifs.h"

#define in IN
#define out OUT
#define optional OPTIONAL
#define wd_ustr UNICODE_STRING
#define wdp_ustr PUNICODE_STRING
#define wd_main DriverEntry

// 裝置、驅動物件類型
typedef DRIVER_OBJECT wd_drv;
typedef DEVICE_OBJECT wd_dev;
typedef DRIVER_OBJECT wd_pdrv;
typedef PDEVICE_OBJECT wd_pdev;

enum {
wd_dev_disk_fs = FILE_DEVICE_DISK_FILE_SYSTEM,
wd_dev_cdrom_fs = FILE_DEVICE_CD_ROM_FILE_SYSTEM,
wd_dev_network_fs = FILE_DEVICE_NETWORK_FILE_SYSTEM
};

// 狀態相關的類型和宏
typedef NTSTATUS wd_stat;

enum {
wd_stat_suc = STATUS_SUCCESS,
wd_stat_path_not_found = STATUS_OBJECT_PATH_NOT_FOUND,
wd_stat_insufficient_res = STATUS_INSUFFICIENT_RESOURCES,
wd_stat_invalid_dev_req = STATUS_INVALID_DEVICE_REQUEST,
wd_stat_no_such_dev = STATUS_NO_SUCH_DEVICE,
wd_stat_image_already_loaded = STATUS_IMAGE_ALREADY_LOADED,
wd_stat_more_processing = STATUS_MORE_PROCESSING_REQUIRED,
wd_stat_pending = STATUS_PENDING
};

_inline wd_bool wd_suc(wd_stat state)
{
return NT_SUCCESS(state);
}

#define wd_printf0 DbgPrint

_inline wd_void wd_ustr_init(in out wd_ustr* str,
in const wd_wchar* chars)
{
RtlInitUnicodeString(str,chars);
};

_inline wd_void wd_ustr_init_em(
in out wd_ustr*str,
in wd_wchar *chars,
in wd_size size)
{
RtlInitEmptyUnicodeString(str,chars,size);
};

wdf.h這個檔案我僅僅節選了需要的部分。以上您已經擁有了一個簡單的“驅動”的完整的代碼。它甚至可以編譯,安裝(請修改sfilter.inf文 件,其方法不過是將多處sfilter改為"our_fs_filter",希望這個過程中您不會出現問題)。然後把wdf.h和 wdf_filter.c放在您建立立的目錄下,這個目錄下還應該有另兩個檔案。一個是Makefile,請從sfilter目錄下拷貝。另一個是 SOURCES,請輸入如下內容:
TARGETNAME=our_fs_filter
TARGETPATH=obj
TARGETTYPE=DRIVER
DRIVERTYPE=FS
BROWSER_INFO=1
SOURCES=wdf_filter.c

使用ddk編譯之後您將得到our_fs_filter.sys.把這個檔案與前所描述的inf檔案同一目錄,按上節所敘述方法安裝。

這個驅動不起任何作用,但是你已經成功的完成了"hello world".

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.