首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

Windows 核心檔案系統辨識器實作完整指南

     編輯:關於VC++

前言

檔案系統辨識器是 NT 核心模式驅動程式,唯一職責:檢查實體儲存媒體格式,辨識出對應檔案系統後載入完整驅動程式。此按需載入機制可節省數百 KB 系統記憶體(如未存取 CD-ROM 則不載入 CDFS)。所有標準 NT 實體媒體檔案系統皆透過辨識器載入。

辨識原理:檔案系統簽名

透過檢查磁碟特定位移的唯一簽名識別檔案系統:

檔案系統簽名特徵
HFS0x4244
NTFS"NTFS" 字串
FAT0xe9、0xeb 或 0x49

簽名位於分區表或分區起始位移處,必須唯一避免誤載入。

掛載流程與 VPB 機制

  • NT 採「存取時掛載」:系統初始化掛載部分磁碟,新分區/可移動媒體於首次存取時掛載。
  • 磁碟代碼為物件管理器符號連結,指向實體裝置物件(非檔案系統裝置)。
  • IO 管理器透過 VPB(Volume Parameter Block)追蹤掛載狀態:VPB->DeviceObject 指向檔案系統裝置物件表示已掛載。
  • 未掛載時,IO 管理器按註冊順序(後註冊優先)呼叫各檔案系統 IRP_MJ_FILE_SYSTEM_CONTROL / IRP_MN_MOUNT_VOLUME。
  • RAW 檔案系統最先註冊,負責註冊 FAT/NTFS/CDFS 三種檔案系統;RAW 磁碟僅支援「整卷存取」。

辨識器運作流程

  1. 辨識器為僅處理掛載請求的特殊檔案系統驅動,建立裝置物件並 IoRegisterFileSystem 註冊。
  2. 收到 IRP_MN_MOUNT_VOLUME,呼叫 RecognizerDetectFileSystem 分析媒體。
  3. 若辨識成功,回傳 STATUS_FS_DRIVER_REQUIRED(特殊狀態碼),IO 管理器隨後發送 IRP_MN_LOAD_FILE_SYSTEM。
  4. 辨識器呼叫 ZwLoadDriver 載入完整檔案系統驅動(登錄路徑為參數)。
  5. 載入成功後,辨識器 IoUnregisterFileSystem 註銷並刪除裝置物件,自身卸載。
  6. 完整檔案系統接管後續掛載請求。

核心實作程式碼架構

全域變數與外部函式宣告


#define FSD_SERVICE_PATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\MyFsd"
#define FSD_RECOGNIZER_NAME L"\\FileSystem\\MyFsdRecognizer"
#define DEVICE_LOGICAL_BLOCKSIZE 512

// IFS Kit 匯出函式
NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);
NTKERNELAPI VOID IoRegisterFileSystem(IN OUT PDEVICE_OBJECT DeviceObject);
NTKERNELAPI VOID IoUnregisterFileSystem(IN OUT PDEVICE_OBJECT DeviceObject);

static PDRIVER_OBJECT RecognizerDriverObject;
static PDEVICE_OBJECT RecognizerDeviceObject;

DriverEntry:初始化與註冊


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
    RecognizerDriverObject = DriverObject;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = RecognizerFsControl;
    DriverObject->DriverUnload = Unload;

    UNICODE_STRING driverName;
    RtlInitUnicodeString(&driverName, FSD_RECOGNIZER_NAME);
    NTSTATUS status = IoCreateDevice(RecognizerDriverObject, 0, &driverName,
        FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &RecognizerDeviceObject);
    if (!NT_SUCCESS(status)) return status;

    IoRegisterFileSystem(RecognizerDeviceObject);
    return STATUS_SUCCESS;
}

RecognizerFsControl:處理掛載/載入請求


static NTSTATUS RecognizerFsControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    if (DeviceObject != RecognizerDeviceObject) return STATUS_NOT_IMPLEMENTED;

    if (irpSp->MinorFunction != IRP_MN_MOUNT_VOLUME &&
        irpSp->MinorFunction != IRP_MN_LOAD_FILE_SYSTEM) {
        return STATUS_NOT_IMPLEMENTED;
    }

    if (irpSp->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) {
        UNICODE_STRING driverName;
        RtlInitUnicodeString(&driverName, FSD_SERVICE_PATH);
        NTSTATUS status = ZwLoadDriver(&driverName);
        Irp->IoStatus.Status = status;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        if (NT_SUCCESS(status)) {
            IoUnregisterFileSystem(RecognizerDeviceObject);
            IoDeleteDevice(RecognizerDeviceObject);
            RecognizerDeviceObject = NULL;
        }
        return status;
    }

    // IRP_MN_MOUNT_VOLUME
    NTSTATUS status = RecognizerDetectFileSystem(Irp);
    if (NT_SUCCESS(status)) {
        Irp->IoStatus.Status = STATUS_FS_DRIVER_REQUIRED;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_FS_DRIVER_REQUIRED;
    }
    Irp->IoStatus.Status = STATUS_UNRECOGNIZED_VOLUME;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_UNRECOGNIZED_VOLUME;
}

RecognizerDetectFileSystem:實際偵測邏輯(需依檔案系統客製)


static NTSTATUS RecognizerDetectFileSystem(PIRP Irp) {
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    PVPB vpb = irpSp->Parameters.MountVolume.Vpb;
    PDEVICE_OBJECT mediaDeviceObject = irpSp->Parameters.MountVolume.DeviceObject;

    // 1. 取得分區資訊 (IOCTL_DISK_GET_PARTITION_INFORMATION)
    // 2. 讀取關鍵磁區 (RecognizerReadDiskSector)
    // 3. 比對檔案系統簽名
    // 4. 成功回傳 STATUS_SUCCESS,失敗回傳錯誤碼
    return STATUS_UNRECOGNIZED_VOLUME; // 預設失敗
}

輔助函式:RecognizerIoControl / RecognizerReadDiskSector

  • RecognizerIoControl:同步發送 IOCTL 至下層驅動取得媒體幾何資訊。
  • RecognizerReadDiskSector:同步讀取指定邏輯磁區(相對分區起始),配置非分頁快取對齊記憶體,使用 IRP_MJ_READ。

兩函式均在 PASSIVE_LEVEL 執行,可安全使用 KeWaitForSingleObject 等待完成。

登錄設定與啟動順序


// 辨識器:系統啟動載入 (Start=0x1)
SYSTEM\CurrentControlSet\Services\MyFsdRecognizer
    Group: "File system"
    Start: 0x1 (Boot)
    Type: 0x8 (File system driver)

// 完整檔案系統:手動載入 (Start=0x3),由辨識器 ZwLoadDriver 觸發
SYSTEM\CurrentControlSet\Services\MyFsd
    Group: "File system"
    Start: 0x3 (Demand)
    Type: 0x2 (File system driver)

結語

檔案系統辨識器雖簡單,卻是實現「按需載入」、最小化記憶體佔用的關鍵元件。掌握其架構與 IRP 流程,是開發客製化檔案系統驅動的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved