|
Posted on 2008-09-10 12:28 沒畫完的畫 閱讀(1707) 評論(3) 編輯 收藏 引用 所屬分類: Windows Driver
上一集看 FileDisk 的代碼,沒看出個所以然…… 本集繼續…… 看下 FileDisk 的應用層 Mount 時的實現代碼
int FileDiskMount(int DeviceNumber, POPEN_FILE_INFORMATION OpenFileInformation, char DriveLetter, BOOLEAN CdImage)
  {
char VolumeName[] = "\\\\.\\ :";
char DeviceName[255];
HANDLE Device;
DWORD BytesReturned;
VolumeName[4] = DriveLetter;
Device = CreateFile(
VolumeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL
);
if (Device != INVALID_HANDLE_VALUE)
 {
SetLastError(ERROR_BUSY);
PrintLastError(&VolumeName[4]);
return -1;
}

if (CdImage)
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
}
else
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
}

if (!DefineDosDevice(
DDD_RAW_TARGET_PATH,
&VolumeName[4],
DeviceName
))
 {
PrintLastError(&VolumeName[4]);
return -1;
}
else
 {
printf("DefineDosDevice %s %s \n", &VolumeName[4], DeviceName);
}
Device = CreateFile(
VolumeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL
);
if (Device == INVALID_HANDLE_VALUE)
 {
PrintLastError(&VolumeName[4]);
DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
return -1;
}
if (!DeviceIoControl(
Device,
IOCTL_FILE_DISK_OPEN_FILE,
OpenFileInformation,
sizeof(OPEN_FILE_INFORMATION) + OpenFileInformation->FileNameLength - 1,
NULL,
0,
&BytesReturned,
NULL
))
 {
PrintLastError("FileDisk:");
DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
return -1;
}
return 0;
}

在執行 DefineDosDevice() 時,把 傳入 DefineDosDevice() 的參數打印出來看一下先…… 顯示結果: DefineDosDevice e: \Device\FileDisk\FileDisk0
Mount 成功后,用 Winobj.exe 查看,奇怪的是它并沒有在 設備目錄 \GLOBAL??\ 下面生成一個 e: 的別名
問題:應用層的 DefineDosDevice() 不是相當于 驅動層的 IoCreateSymbolicLink() 函數? 那為何不會生成 e: 這樣的別名, 沒有生成別名,在應用層又是怎么能夠直接訪問 e: 的呢? --- 迷惘ing
于是在 FileDiskMount() 函數中增加一些語句嘗試一下
int
FileDiskMount(
int DeviceNumber,
POPEN_FILE_INFORMATION OpenFileInformation,
char DriveLetter,
BOOLEAN CdImage
)
  {
char VolumeName[] = "\\\\.\\ :";
char DeviceName[255];
HANDLE Device;
DWORD BytesReturned;
VolumeName[4] = DriveLetter;
printf("Enter FileDiskMount \n");
printf("FileDiskMount CreateFile VolumeName = %s\n", VolumeName);
Device = CreateFile(
VolumeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL
);
if (Device != INVALID_HANDLE_VALUE)
 {
// 這里沒有調用 CloseHandle() 將 Device 關閉 -_-!!
SetLastError(ERROR_BUSY);
PrintLastError(&VolumeName[4]);
return -1;
}

if (CdImage)
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
}
else
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
}

printf("FileDiskMount DefineDosDevice VolumeName = %s DeviceName = %s \n", &VolumeName[4], DeviceName);
if (!DefineDosDevice(
DDD_RAW_TARGET_PATH,
&VolumeName[4],
DeviceName
))
 {
PrintLastError(&VolumeName[4]);
return -1;
}

printf("FileDiskMount CreateFile VolumeName = %s\n", VolumeName);
Device = CreateFile(
VolumeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL
);
if (Device == INVALID_HANDLE_VALUE)
 {
PrintLastError(&VolumeName[4]);
DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
return -1;
}
if (!DeviceIoControl(
Device,
IOCTL_FILE_DISK_OPEN_FILE,
OpenFileInformation,
sizeof(OPEN_FILE_INFORMATION) + OpenFileInformation->FileNameLength - 1,
NULL,
0,
&BytesReturned,
NULL
))
 {
PrintLastError("FileDisk:");
DefineDosDevice(DDD_REMOVE_DEFINITION, &VolumeName[4], NULL);
return -1;
}
// 在最后 Device 沒有進行 CloseHandle() ??
return 0;
}

運行 filedisk /mount 之后,輸出結果如下 Enter FileDiskMount FileDiskMount CreateFile VolumeName = \\.\e: FileDiskMount DefineDosDevice VolumeName = e: DeviceName = \Device\FileDisk\FileDisk0 FileDiskMount CreateFile VolumeName = \\.\e:
FileDiskMount 的函數先是 用 CreateFile 嘗試打開 \\.\e 這個設備, 確定 e: 這個盤符沒有被占用后,就用 DefineDosDevice() 函數 把 e: 這個盤符指向 \Device\FileDisk\FileDisk0 這個設備 接下來,再用 CreateFile 打開 \\.\e 這個設備 然后調用 DeviceIoControl() 給 \\.\e 這個設備發送 IOCTL_FILE_DISK_OPEN_FILE 這個 Control Code
昨天試過用 DeviceIoControl() 函數,但并未顯示出設備出來 難道調用 DeviceIoControl() 函數后,還需要向這個設備發 IOCTL_FILE_DISK_OPEN_FILE 這個 Control Code , “虛擬的分區”才會顯示出來?
于是,決定嘗試下,把后來的向設備發送 IOCTL_FILE_DISK_OPEN_FILE 的相關代碼去掉, 將 FileDiskMount() 的代碼修改為
int
FileDiskMount(
int DeviceNumber,
POPEN_FILE_INFORMATION OpenFileInformation,
char DriveLetter,
BOOLEAN CdImage
)
  {
char VolumeName[] = "\\\\.\\ :";
char DeviceName[255];
HANDLE Device;
DWORD BytesReturned;
VolumeName[4] = DriveLetter;
printf("Enter FileDiskMount \n");
printf("FileDiskMount CreateFile VolumeName = %s\n", VolumeName);
Device = CreateFile(
VolumeName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING,
NULL
);
if (Device != INVALID_HANDLE_VALUE)
 {
SetLastError(ERROR_BUSY);
PrintLastError(&VolumeName[4]);
return -1;
}
if (CdImage)
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
}
else
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
}
printf("FileDiskMount DefineDosDevice VolumeName = %s DeviceName = %s \n", &VolumeName[4], DeviceName);
if (!DefineDosDevice(
DDD_RAW_TARGET_PATH,
&VolumeName[4],
DeviceName
))
 {
PrintLastError(&VolumeName[4]);
return -1;
}
return 0;
}


運行結果: C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\filediskexe.exe" /mount 0 c:\1.txt 9M e: Enter FileDiskMount FileDiskMount CreateFile VolumeName = \\.\e: FileDiskMount DefineDosDevice VolumeName = e: DeviceName = \Device\FileDisk\File Disk0
仍然可以在我的電腦里顯示 e: 盤這個分區,但雙擊進入時,會有一個錯誤提示“無法訪問 E:\ 設備未就緒。”
昨天試過調用完 DefineDosDevice() 后,在我的電腦里,還是沒有把那個虛擬分區顯示出來,為什么 FileDisk 就可以? 將 FileDiskMount() 再修改為
int
FileDiskMount(
int DeviceNumber,
POPEN_FILE_INFORMATION OpenFileInformation,
char DriveLetter,
BOOLEAN CdImage
)
  {
char VolumeName[] = "\\\\.\\ :";
char DeviceName[255];
VolumeName[4] = DriveLetter;
printf("Enter FileDiskMount \n");
if (CdImage)
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
}
else
 {
sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
}
printf("FileDiskMount DefineDosDevice VolumeName = %s DeviceName = %s \n", &VolumeName[4], DeviceName);
if (!DefineDosDevice(
DDD_RAW_TARGET_PATH,
&VolumeName[4],
DeviceName
))
 {
PrintLastError(&VolumeName[4]);
return -1;
}
return 0;
}

運行 C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\testfilediskexe.exe" /mount 0 c:\1.txt 8M e: Enter FileDiskMount FileDiskMount DefineDosDevice VolumeName = e: DeviceName = \Device\FileDisk\File Disk0
結果還是可以在我的電腦中顯示 e: 盤 昨天沒有把虛擬的分區顯示出來,可能性有2個
1、DefineDosDevice() 的調用有問題 2、FileDisk .sys 在調用了 IoCreateDevice() 之后,還做了其它一些東西,而我沒有注意到
于是,決定再次嘗試下用 DefineDosDevice() 能不能把虛擬的分區顯示出來 .sys 的代碼
#include <ntddk.h>
#include <ntdddisk.h>
#define DEVICE_NAME L"\\DosDevices\\SimpleDriver"
#define SECTOR_SIZE 512
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
  {
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uniNameString;
DEVICE_OBJECT *pCDO = NULL;
KdPrint(("SimpleDriver!DriverEntry \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_NAME);
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);
if( !NT_SUCCESS(status) )
return status;
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
DriverObject->MajorFunction[IRP_MJ_READ] = DeviceReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DeviceReadWrite;
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
  {
PAGED_CODE();
KdPrint(("SimpleDriver!DriverUnload \n"));
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
PAGED_CODE();
KdPrint(("SimpleDriver!DeviceCreateClose \n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
NTSTATUS status = STATUS_SUCCESS;
ULONG nIoCtrlCodes = 0; // IO控制碼
PIO_STACK_LOCATION IrpStack = NULL; //IRP堆棧
KdPrint(("SimpleDriver!DeviceControl \n"));
//得到當前調用者的IRP
IrpStack = IoGetCurrentIrpStackLocation(Irp);
nIoCtrlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
KdPrint(("SimpleDriver!DeviceControl IoControlCode = 0x%X\n", nIoCtrlCodes));
switch( IrpStack->Parameters.DeviceIoControl.IoControlCode )
 {
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
 {
PDISK_GEOMETRY disk_geometry;
ULONGLONG length;
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_GET_DRIVE_GEOMETRY \n"));
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
 {
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
// #define SECTOR_SIZE 512
disk_geometry->Cylinders.QuadPart = 41940668416 / SECTOR_SIZE / 32 / 2;
disk_geometry->MediaType = FixedMedia;
disk_geometry->TracksPerCylinder = 2;
disk_geometry->SectorsPerTrack = 32;
disk_geometry->BytesPerSector = SECTOR_SIZE;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case IOCTL_DISK_GET_PARTITION_INFO:
 {
PPARTITION_INFORMATION partition_information;
ULONGLONG length;
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_GET_PARTITION_INFO \n"));
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
partition_information->StartingOffset.QuadPart = 0;
partition_information->PartitionLength.QuadPart = 41940668416;
partition_information->HiddenSectors = 1;
partition_information->PartitionNumber = 0;
partition_information->PartitionType = 0;
partition_information->BootIndicator = FALSE;
partition_information->RecognizedPartition = FALSE;
partition_information->RewritePartition = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
}
break;
case IOCTL_DISK_IS_WRITABLE:
 {
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_IS_WRITABLE \n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
break;
case IOCTL_DISK_SET_PARTITION_INFO:
 {
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_SET_PARTITION_INFO \n"));
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SET_PARTITION_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
}
break;
case IOCTL_DISK_VERIFY:
 {
PVERIFY_INFORMATION verify_information;
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_VERIFY \n"));
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = verify_information->Length;
}
break;
case IOCTL_DISK_CHECK_VERIFY:
 {
KdPrint(("SimpleDriver!DeviceControl IOCTL_DISK_CHECK_VERIFY \n"));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
};
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DeviceReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
PIO_STACK_LOCATION io_stack;
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (io_stack->Parameters.Read.Length == 0)
 {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
#pragma code_seg()

.exe 代碼
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
void mount()
  {
if (!DefineDosDevice(DDD_RAW_TARGET_PATH, "e:",
"\\\\.\\SimpleDriver"
))
 {
printf("DefineDosDevice Error ErrCode = %d", ::GetLastError());
}
else
 {
printf("DefineDosDevice OK ErrCode = %d", ::GetLastError());
}
}

int main(int argc, char *argv[])
  {
mount();
return 0;
}

運行結果: C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\testDriverTalk.exe" DefineDosDevice OK ErrCode = 0
但很遺憾!!!!! e: 盤就是不顯示出來
難道跟設備的路徑有關系??? FileDisk 創建的設備路徑是: \Device\FileDisk\File 而上述的SimpleDriver 創建的設備路徑是 \DosDevices\SimpleDriver
于是嘗試將將 .sys 代碼中 #define DEVICE_NAME L"\\DosDevices\\SimpleDriver" 改為: #define DEVICE_NAME L"\\Device\\SimpleDriver"
編譯…… 用 OSRLOADER.exe 加態完驅動后,再用 Winobj.exe 確定了 SimpleDriver 所在的設備路徑是 \Device\SimpleDriver
再加 .exe 的 if (!DefineDosDevice(DDD_RAW_TARGET_PATH, "e:", "\\\\.\\SimpleDriver" ))
改為 if (!DefineDosDevice(DDD_RAW_TARGET_PATH, "e:", "\\Device\\SimpleDriver" ))
編譯……,運行 運行結果: C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\testDriverTalk.exe" DefineDosDevice OK ErrCode = 0
恭喜,恭喜!!!!!!!! 在我的電腦中,E: 這個虛擬的分區終于顯示出來了
如此證明,昨天 調用 DefineDosDevice() 后,E: 盤沒顯示出來,跟 設備的路徑是有關的 但具體原因未知 設備路徑:\DosDevices\SimpleDriver 調用 DefineDosDevice() 后, 不顯示 E: 盤 設備路徑:\Device\SimpleDriver 調用 DefineDosDevice() 后, 顯示 E: 盤
雙擊 E: 盤 提示錯誤信息: “無法訪問 E:\ 函數不正確。” 具體原因不詳, 有可能是 .sys 沒有處理相關 IRP 的原因,需要進一步研究
接下來,想試一下,直接在加載驅動的時候,調用 IoCreateSymbolicLink
修改 .sys 代碼為
#include <ntddk.h>
#include <ntdddisk.h>
#define DEVICE_NAME L"\\Device\\SimpleDriver"
#define DEVICE_LINK_NAME L"\\\\.\\e"
#define SECTOR_SIZE 512

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS DeviceReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
#pragma code_seg("INIT")
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
  {
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING uniNameString;
UNICODE_STRING uniLinkString;
DEVICE_OBJECT *pCDO = NULL;
KdPrint(("SimpleDriver!DriverEntry \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_NAME);
status = IoCreateDevice(DriverObject, 0, &uniNameString, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN, FALSE, &pCDO);
if( !NT_SUCCESS(status) )
return status;
RtlInitUnicodeString(&uniLinkString, DEVICE_LINK_NAME);
status = IoCreateSymbolicLink(&uniLinkString, &uniNameString);
if(!NT_SUCCESS(status))
return status;
DriverObject->DriverUnload = DriverUnload;
DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
DriverObject->MajorFunction[IRP_MJ_READ] = DeviceReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = DeviceReadWrite;
return STATUS_SUCCESS;
}
#pragma code_seg("PAGE")
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
  {
UNICODE_STRING uniNameString;
PAGED_CODE();
KdPrint(("SimpleDriver!DriverUnload \n"));
RtlInitUnicodeString(&uniNameString, DEVICE_LINK_NAME);
IoDeleteSymbolicLink(&uniNameString);
IoDeleteDevice(DriverObject->DeviceObject);
}
NTSTATUS DeviceCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
PAGED_CODE();
KdPrint(("SimpleDriver!DeviceCreateClose \n"));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
NTSTATUS status = STATUS_SUCCESS;
ULONG nIoCtrlCodes = 0; // IO控制碼
PIO_STACK_LOCATION IrpStack = NULL; //IRP堆棧
KdPrint(("SimpleDriver!DeviceControl \n"));
//得到當前調用者的IRP
IrpStack = IoGetCurrentIrpStackLocation(Irp);
nIoCtrlCodes = IrpStack->Parameters.DeviceIoControl.IoControlCode;
KdPrint(("SimpleDriver!DeviceControl IoControlCode = 0x%X\n", nIoCtrlCodes));
switch( IrpStack->Parameters.DeviceIoControl.IoControlCode )
 {
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
 {
PDISK_GEOMETRY disk_geometry;
ULONGLONG length;
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY))
 {
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
disk_geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
// #define SECTOR_SIZE 512
disk_geometry->Cylinders.QuadPart = 41940668416 / SECTOR_SIZE / 32 / 2;
disk_geometry->MediaType = FixedMedia;
disk_geometry->TracksPerCylinder = 2;
disk_geometry->SectorsPerTrack = 32;
disk_geometry->BytesPerSector = SECTOR_SIZE;
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
case IOCTL_DISK_GET_PARTITION_INFO:
 {
PPARTITION_INFORMATION partition_information;
ULONGLONG length;
if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
break;
}
partition_information = (PPARTITION_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
partition_information->StartingOffset.QuadPart = 0;
partition_information->PartitionLength.QuadPart = 41940668416;
partition_information->HiddenSectors = 1;
partition_information->PartitionNumber = 0;
partition_information->PartitionType = 0;
partition_information->BootIndicator = FALSE;
partition_information->RecognizedPartition = FALSE;
partition_information->RewritePartition = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
}
break;
case IOCTL_DISK_IS_WRITABLE:
 {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
break;
}
break;
case IOCTL_DISK_SET_PARTITION_INFO:
 {
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SET_PARTITION_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
}
break;
case IOCTL_DISK_VERIFY:
 {
PVERIFY_INFORMATION verify_information;
if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION))
 {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
break;
}
verify_information = (PVERIFY_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = verify_information->Length;
}
break;
case IOCTL_DISK_CHECK_VERIFY:
 {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
};
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS DeviceReadWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
PIO_STACK_LOCATION io_stack;
io_stack = IoGetCurrentIrpStackLocation(Irp);
if (io_stack->Parameters.Read.Length == 0)
 {
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
#pragma code_seg()

使用 OSRLOADER.exe 加載 .sys 時,提示錯誤信息 “文件名、目錄名或卷標語法不正確”, 應該是 #define DEVICE_LINK_NAME L"\\\\.\\e" 這個非法了
嘗試修改為 #define DEVICE_LINK_NAME L"\\.\\e" 加載時提示錯誤信息“系統找不到指定的路徑”,暈,這好像是應用層調用的路徑,
再嘗試修改為 #define DEVICE_NAME L"\\Device\\SimpleDriver" #define DEVICE_LINK_NAME L"\\DosDevices\\x:"
加載成功 用 Winobj.exe 查看
設備目錄有 \Device\SimpleDriver 也有 \GLOBAL??\X:
但在我的電腦中并沒有顯示 x: 出來 奇怪的地方是 用 DefineDosDevice() 函數不會在 \GLOBAL??\ 下面生成分區的別名,但它又怎么訪問得到呢? 而 使用 IoCreateSymbolicLink() 可以在 \GLOBAL??\ 下生成別名,但在我的電腦中卻又不會顯示
DefineDosDevice() 函數的作用不是相當于 IoCreateSymbolicLink()? -- 未解決
本集終于可以實現虛擬出一個分區的功能了,但還有很多細節問題需要深入再研究,查找相關資料 問題 1、 設備路徑:\DosDevices\SimpleDriver 調用 DefineDosDevice() 后, 不顯示 E: 盤 設備路徑:\Device\SimpleDriver 調用 DefineDosDevice() 后, 顯示 E: 盤
原因是: 未解決 2、用 DefineDosDevice() 函數不會在 \GLOBAL??\ 下面生成分區的別名,但它又怎么訪問得到呢? 而 使用 IoCreateSymbolicLink() 可以在 \GLOBAL??\ 下生成別名,但在我的電腦中卻又不會顯示
DefineDosDevice() 函數的作用不是相當于 IoCreateSymbolicLink()? -- 未解決
--- 6集 完 ---
Feedback
# re: 關于 TrueCrypt 第6集 回復 更多評論
2010-08-28 23:19 by
第一個問題可以回答,\DosDevices\SimpleDriver是符號連接,指向\Device\SimpleDriver,\Device\SimpleDriver才是設備名,DefineDosDevice要用設備名。
第二個問題我現在正在苦惱中,如果在驅動中或者在處理內核進程向驅動發送的IRP過程中使用IoCreateSymbolicLink創建符號連接,這個連接在Global中就能顯示出來,如果在處理用戶進程想驅動發送的IRP過程中使用IoCreateSymbolicLink創建符號連接或者使用DefineDosDevice,這個連接在Global中就顯示不出來(TrueCrypt居然可以,但是我自己仿照truecrypt寫的也不行,直接編譯TrueCrypt代碼沒成功)。
這兩種連接是不同的,好像可以同時創建成功,但是前者在內核中可以使用,后者則不可。比如你加載一個驅動,使用J:這個符號連接路徑,前者可以成功啟動,后者則不行。所以,如果你的驅動在映射的遠程盤上,就會加載失敗。
# re: 關于 TrueCrypt 第6集 回復 更多評論
2010-08-28 23:20 by
# re: 關于 TrueCrypt 第6集 回復 更多評論
2010-08-29 12:33 by
哈哈,終于知道了,用DefineDosDevice定義的符號連接在Session下面,用windbg調試truecrypt驅動終于知道了它是在MountManagerMount中用IoBuildDeviceIoControlRequest實現了global和session下面都有符號連接。
|