檔案系統辨識器是 NT 核心模式驅動程式,唯一職責:檢查實體儲存媒體格式,辨識出對應檔案系統後載入完整驅動程式。此按需載入機制可節省數百 KB 系統記憶體(如未存取 CD-ROM 則不載入 CDFS)。所有標準 NT 實體媒體檔案系統皆透過辨識器載入。
透過檢查磁碟特定位移的唯一簽名識別檔案系統:
| 檔案系統 | 簽名特徵 |
|---|---|
| HFS | 0x4244 |
| NTFS | "NTFS" 字串 |
| FAT | 0xe9、0xeb 或 0x49 |
簽名位於分區表或分區起始位移處,必須唯一避免誤載入。
VPB->DeviceObject 指向檔案系統裝置物件表示已掛載。IRP_MJ_FILE_SYSTEM_CONTROL / IRP_MN_MOUNT_VOLUME。IoRegisterFileSystem 註冊。IRP_MN_MOUNT_VOLUME,呼叫 RecognizerDetectFileSystem 分析媒體。STATUS_FS_DRIVER_REQUIRED(特殊狀態碼),IO 管理器隨後發送 IRP_MN_LOAD_FILE_SYSTEM。ZwLoadDriver 載入完整檔案系統驅動(登錄路徑為參數)。IoUnregisterFileSystem 註銷並刪除裝置物件,自身卸載。
#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;
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;
}
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;
}
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:同步發送 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 流程,是開發客製化檔案系統驅動的基石。