|
Posted on 2008-09-10 12:28 沒(méi)畫(huà)完的畫(huà) 閱讀(1707) 評(píng)論(3) 編輯 收藏 引用 所屬分類(lèi): Windows Driver
上一集看 FileDisk 的代碼,沒(méi)看出個(gè)所以然…… 本集繼續(xù)…… 看下 FileDisk 的應(yīng)用層 Mount 時(shí)的實(shí)現(xiàn)代碼
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;
}

在執(zhí)行 DefineDosDevice() 時(shí),把 傳入 DefineDosDevice() 的參數(shù)打印出來(lái)看一下先…… 顯示結(jié)果: DefineDosDevice e: \Device\FileDisk\FileDisk0
Mount 成功后,用 Winobj.exe 查看,奇怪的是它并沒(méi)有在 設(shè)備目錄 \GLOBAL??\ 下面生成一個(gè) e: 的別名
問(wèn)題:應(yīng)用層的 DefineDosDevice() 不是相當(dāng)于 驅(qū)動(dòng)層的 IoCreateSymbolicLink() 函數(shù)? 那為何不會(huì)生成 e: 這樣的別名, 沒(méi)有生成別名,在應(yīng)用層又是怎么能夠直接訪問(wèn) e: 的呢? --- 迷惘ing
于是在 FileDiskMount() 函數(shù)中增加一些語(yǔ)句嘗試一下
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)
 {
// 這里沒(méi)有調(diào)用 CloseHandle() 將 Device 關(guān)閉 -_-!!
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 沒(méi)有進(jìn)行 CloseHandle() ??
return 0;
}

運(yùn)行 filedisk /mount 之后,輸出結(jié)果如下 Enter FileDiskMount FileDiskMount CreateFile VolumeName = \\.\e: FileDiskMount DefineDosDevice VolumeName = e: DeviceName = \Device\FileDisk\FileDisk0 FileDiskMount CreateFile VolumeName = \\.\e:
FileDiskMount 的函數(shù)先是 用 CreateFile 嘗試打開(kāi) \\.\e 這個(gè)設(shè)備, 確定 e: 這個(gè)盤(pán)符沒(méi)有被占用后,就用 DefineDosDevice() 函數(shù) 把 e: 這個(gè)盤(pán)符指向 \Device\FileDisk\FileDisk0 這個(gè)設(shè)備 接下來(lái),再用 CreateFile 打開(kāi) \\.\e 這個(gè)設(shè)備 然后調(diào)用 DeviceIoControl() 給 \\.\e 這個(gè)設(shè)備發(fā)送 IOCTL_FILE_DISK_OPEN_FILE 這個(gè) Control Code
昨天試過(guò)用 DeviceIoControl() 函數(shù),但并未顯示出設(shè)備出來(lái) 難道調(diào)用 DeviceIoControl() 函數(shù)后,還需要向這個(gè)設(shè)備發(fā) IOCTL_FILE_DISK_OPEN_FILE 這個(gè) Control Code , “虛擬的分區(qū)”才會(huì)顯示出來(lái)?
于是,決定嘗試下,把后來(lái)的向設(shè)備發(fā)送 IOCTL_FILE_DISK_OPEN_FILE 的相關(guān)代碼去掉, 將 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;
}


運(yùn)行結(jié)果: 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: 盤(pán)這個(gè)分區(qū),但雙擊進(jìn)入時(shí),會(huì)有一個(gè)錯(cuò)誤提示“無(wú)法訪問(wèn) E:\ 設(shè)備未就緒。”
昨天試過(guò)調(diào)用完 DefineDosDevice() 后,在我的電腦里,還是沒(méi)有把那個(gè)虛擬分區(qū)顯示出來(lái),為什么 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;
}

運(yùn)行 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
結(jié)果還是可以在我的電腦中顯示 e: 盤(pán) 昨天沒(méi)有把虛擬的分區(qū)顯示出來(lái),可能性有2個(gè)
1、DefineDosDevice() 的調(diào)用有問(wèn)題 2、FileDisk .sys 在調(diào)用了 IoCreateDevice() 之后,還做了其它一些東西,而我沒(méi)有注意到
于是,決定再次嘗試下用 DefineDosDevice() 能不能把虛擬的分區(qū)顯示出來(lái) .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"));
//得到當(dāng)前調(diào)用者的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;
}

運(yùn)行結(jié)果: C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\testDriverTalk.exe" DefineDosDevice OK ErrCode = 0
但很遺憾!!!!! e: 盤(pán)就是不顯示出來(lái)
難道跟設(shè)備的路徑有關(guān)系??? FileDisk 創(chuàng)建的設(shè)備路徑是: \Device\FileDisk\File 而上述的SimpleDriver 創(chuàng)建的設(shè)備路徑是 \DosDevices\SimpleDriver
于是嘗試將將 .sys 代碼中 #define DEVICE_NAME L"\\DosDevices\\SimpleDriver" 改為: #define DEVICE_NAME L"\\Device\\SimpleDriver"
編譯…… 用 OSRLOADER.exe 加態(tài)完驅(qū)動(dòng)后,再用 Winobj.exe 確定了 SimpleDriver 所在的設(shè)備路徑是 \Device\SimpleDriver
再加 .exe 的 if (!DefineDosDevice(DDD_RAW_TARGET_PATH, "e:", "\\\\.\\SimpleDriver" ))
改為 if (!DefineDosDevice(DDD_RAW_TARGET_PATH, "e:", "\\Device\\SimpleDriver" ))
編譯……,運(yùn)行 運(yùn)行結(jié)果: C:\Documents and Settings\test>"C:\Documents and Settings\test\桌面\testDriverTalk.exe" DefineDosDevice OK ErrCode = 0
恭喜,恭喜!!!!!!!! 在我的電腦中,E: 這個(gè)虛擬的分區(qū)終于顯示出來(lái)了
如此證明,昨天 調(diào)用 DefineDosDevice() 后,E: 盤(pán)沒(méi)顯示出來(lái),跟 設(shè)備的路徑是有關(guān)的 但具體原因未知 設(shè)備路徑:\DosDevices\SimpleDriver 調(diào)用 DefineDosDevice() 后, 不顯示 E: 盤(pán) 設(shè)備路徑:\Device\SimpleDriver 調(diào)用 DefineDosDevice() 后, 顯示 E: 盤(pán)
雙擊 E: 盤(pán) 提示錯(cuò)誤信息: “無(wú)法訪問(wèn) E:\ 函數(shù)不正確。” 具體原因不詳, 有可能是 .sys 沒(méi)有處理相關(guān) IRP 的原因,需要進(jìn)一步研究
接下來(lái),想試一下,直接在加載驅(qū)動(dòng)的時(shí)候,調(diào)用 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"));
//得到當(dāng)前調(diào)用者的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 時(shí),提示錯(cuò)誤信息 “文件名、目錄名或卷標(biāo)語(yǔ)法不正確”, 應(yīng)該是 #define DEVICE_LINK_NAME L"\\\\.\\e" 這個(gè)非法了
嘗試修改為 #define DEVICE_LINK_NAME L"\\.\\e" 加載時(shí)提示錯(cuò)誤信息“系統(tǒng)找不到指定的路徑”,暈,這好像是應(yīng)用層調(diào)用的路徑,
再嘗試修改為 #define DEVICE_NAME L"\\Device\\SimpleDriver" #define DEVICE_LINK_NAME L"\\DosDevices\\x:"
加載成功 用 Winobj.exe 查看
設(shè)備目錄有 \Device\SimpleDriver 也有 \GLOBAL??\X:
但在我的電腦中并沒(méi)有顯示 x: 出來(lái) 奇怪的地方是 用 DefineDosDevice() 函數(shù)不會(huì)在 \GLOBAL??\ 下面生成分區(qū)的別名,但它又怎么訪問(wèn)得到呢? 而 使用 IoCreateSymbolicLink() 可以在 \GLOBAL??\ 下生成別名,但在我的電腦中卻又不會(huì)顯示
DefineDosDevice() 函數(shù)的作用不是相當(dāng)于 IoCreateSymbolicLink()? -- 未解決
本集終于可以實(shí)現(xiàn)虛擬出一個(gè)分區(qū)的功能了,但還有很多細(xì)節(jié)問(wèn)題需要深入再研究,查找相關(guān)資料 問(wèn)題 1、 設(shè)備路徑:\DosDevices\SimpleDriver 調(diào)用 DefineDosDevice() 后, 不顯示 E: 盤(pán) 設(shè)備路徑:\Device\SimpleDriver 調(diào)用 DefineDosDevice() 后, 顯示 E: 盤(pán)
原因是: 未解決 2、用 DefineDosDevice() 函數(shù)不會(huì)在 \GLOBAL??\ 下面生成分區(qū)的別名,但它又怎么訪問(wèn)得到呢? 而 使用 IoCreateSymbolicLink() 可以在 \GLOBAL??\ 下生成別名,但在我的電腦中卻又不會(huì)顯示
DefineDosDevice() 函數(shù)的作用不是相當(dāng)于 IoCreateSymbolicLink()? -- 未解決
--- 6集 完 ---
Feedback
第一個(gè)問(wèn)題可以回答,\DosDevices\SimpleDriver是符號(hào)連接,指向\Device\SimpleDriver,\Device\SimpleDriver才是設(shè)備名,DefineDosDevice要用設(shè)備名。
第二個(gè)問(wèn)題我現(xiàn)在正在苦惱中,如果在驅(qū)動(dòng)中或者在處理內(nèi)核進(jìn)程向驅(qū)動(dòng)發(fā)送的IRP過(guò)程中使用IoCreateSymbolicLink創(chuàng)建符號(hào)連接,這個(gè)連接在Global中就能顯示出來(lái),如果在處理用戶進(jìn)程想驅(qū)動(dòng)發(fā)送的IRP過(guò)程中使用IoCreateSymbolicLink創(chuàng)建符號(hào)連接或者使用DefineDosDevice,這個(gè)連接在Global中就顯示不出來(lái)(TrueCrypt居然可以,但是我自己仿照truecrypt寫(xiě)的也不行,直接編譯TrueCrypt代碼沒(méi)成功)。
這兩種連接是不同的,好像可以同時(shí)創(chuàng)建成功,但是前者在內(nèi)核中可以使用,后者則不可。比如你加載一個(gè)驅(qū)動(dòng),使用J:這個(gè)符號(hào)連接路徑,前者可以成功啟動(dòng),后者則不行。所以,如果你的驅(qū)動(dòng)在映射的遠(yuǎn)程盤(pán)上,就會(huì)加載失敗。
哈哈,終于知道了,用DefineDosDevice定義的符號(hào)連接在Session下面,用windbg調(diào)試truecrypt驅(qū)動(dòng)終于知道了它是在MountManagerMount中用IoBuildDeviceIoControlRequest實(shí)現(xiàn)了global和session下面都有符號(hào)連接。
|