2008.09.04
此篇是(關于 TrueCrypt)的續集, 在看此篇前先看上篇,不然會很危險
從 DriverEntry 看起
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
// 讀取注冊時使用的變量
UNICODE_STRING parameter_path;
RTL_QUERY_REGISTRY_TABLE query_table[2];
ULONG n_devices;
NTSTATUS status;
UNICODE_STRING device_dir_name;
OBJECT_ATTRIBUTES object_attributes;
ULONG n;
USHORT n_created_devices;
// #define PARAMETER_KEY L"\\Parameters"
parameter_path.Length = 0;
parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY);
parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength);
if (parameter_path.Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyUnicodeString(¶meter_path, RegistryPath);
RtlAppendUnicodeToString(¶meter_path, PARAMETER_KEY);
RtlZeroMemory(&query_table[0], sizeof(query_table));
query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
query_table[0].Name = NUMBEROFDEVICES_VALUE; // #define NUMBEROFDEVICES_VALUE L"NumberOfDevices"
query_table[0].EntryContext = &n_devices;
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
parameter_path.Buffer,
&query_table[0],
NULL,
NULL
);
ExFreePool(parameter_path.Buffer);
if (!NT_SUCCESS(status))
{
// 如果讀取注冊表失敗, 則默認為 4個
// #define DEFAULT_NUMBEROFDEVICES 4
KdPrint(("FileDisk: Query registry failed, using default values.\n"));
n_devices = DEFAULT_NUMBEROFDEVICES;
}
// 下面的代碼完成在設備目錄中創建對應的目錄
/*
* #define DEVICE_BASE_NAME _T("\\FileDisk")
* #define DEVICE_DIR_NAME _T("\\Device") DEVICE_BASE_NAME
* #define DEVICE_NAME_PREFIX DEVICE_DIR_NAME DEVICE_BASE_NAME
*/
RtlInitUnicodeString(&device_dir_name, DEVICE_DIR_NAME);
InitializeObjectAttributes(
&object_attributes,
&device_dir_name,
OBJ_PERMANENT,
NULL,
NULL
);
status = ZwCreateDirectoryObject(
&dir_handle,
DIRECTORY_ALL_ACCESS,
&object_attributes
);
if (!NT_SUCCESS(status))
{
return status;
}
// 將上面創建的設備目錄屬性設置為 臨時
ZwMakeTemporaryObject(dir_handle);
for (n = 0, n_created_devices = 0; n < n_devices; n++)
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_DISK);
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
for (n = 0; n < n_devices; n++)
{
status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_CD_ROM);
if (NT_SUCCESS(status))
{
n_created_devices++;
}
}
if (n_created_devices == 0)
{
ZwClose(dir_handle);
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FileDiskCreateClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FileDiskReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl;
DriverObject->DriverUnload = FileDiskUnload;
return STATUS_SUCCESS;
}
DriverEntry() 做的大概東西就是:
1、讀取注冊表的
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\FileDisk\Parameters\
下面的 NumberOfDevices 這個值
2、如果指定的設備目錄(\\FileDisk\\Device)不存在, 創建對應的設備目錄
3、然后調用 IoCreateDevice() 在創建的設備目錄下創建設備
4、每創建一個設備都同時創建一個線程,具體用來做什么,正在摸索中.........
問題1: RTL_QUERY_REGISTRY_TABLE query_table[2]; // 這里為何要定義為 2?
-- 未解決,先看下在應用層讀取注冊表是如何做的先!
問題2: 將上面創建的設備目錄屬性設置為 臨時 ZwMakeTemporaryObject(dir_handle);
-- 未解決,設置屬性為臨時的作用是? 重啟系統時這個設備目錄會不存在? 如果不設置這個屬性,重啟系統后還存在?
問題3: 為何在 DriverEntry() 里就用 IoCreateDevice() 創建設備?不是等應用層運行用 mount 后才創建設備的嗎?
-- 未解決,先郁悶一下?。。?!
問題4: 關于[設備目錄]的疑問,[設備目錄]是個什么東東?……
-- 未解決,在N久前,好像看過這樣一篇文章,講的是 Windows 下面所有內核對象都是采用對象管理 之類的
有空再找下這方面的詳細資料!?。?再郁悶一下?。?!
問題5、FileDiskCreateDevice() 函數中在調用了 IoCreateDevice() 創建設備后
設置了 device_object 的屬性, 這些語句的作用是什么?
device_object->Flags |= DO_DIRECT_IO;
device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;
device_extension->media_in_device = FALSE;
if (DeviceType == FILE_DEVICE_CD_ROM)
{
device_object->Characteristics |= FILE_READ_ONLY_DEVICE;
device_extension->read_only = TRUE;
}
另外奇怪的是, 為何設置 device_object 的屬性后,不需要調 update() 之類的函數,
重新設置的屬性在設置完后就生效????
問題6、FileDisk.sys 在 DriverEntry() 就創建了四個設備,四條內核線程,導致 mount 最多就 4 個設備,
為何不做成可以動態加載N個設備?(因為我見過其它類似于 TrueCrypt 的工具,是可以動態Mount N個分區的)
接下來,應該先了解下 驅動與應用層的通信方式是怎樣的先!Google 一下