Здраствуйте. Вот решил написать чтото в стиле Dekart Private Disk, True Crypt, Safe House и тд. Для реализации задачи нужно сделать небольшой драйвер который создаст диск и будет принимать запросы к диску перенаправляя их утилите написаной на Делфи2007 которая уже в реальном пользовательском режиме будет их (запросы) обрабатывать и возвращать результат. Драйвера раньше вообще не писал, 3 недели перечитываю Солдатова Разобрался с драйвером. Небольшая утилитка на Delphi2007 связывается и обменивается IRP. За логикой решил делать так... когда приходят IRP запросы драйверу он помещает их в очередь и возвращает STATUS_PENDING. После чего утилита обращаясь к драйверу, скажем, по IOCTL_DISK_GET_IRP (своя функция) забирает из очереди по одному запросу которые накопились. Но... при обращении утилиты к функции CreateFile: а) в драйвере вообще не срабатывает событие IRP_MJ_CREATE, хотя в солдатове чёрным по белому сказано "CreateFile=IRP_MJ_CREATE". Точно так же никогда не срабатывает IRP_MJ_CLOSE. В то же время связь с драйвером устанавливается успешно. б) автоматом формируется несколько IRP пакетов от имени утилиты драйверу (не мной) в момент исполнения CreateFile. Одна из них IOCTL_DISK_GET_DRIVE_GEOMETRY. Вообще не доганяю причём она тут. Это не критично конечно но драйвер то не отличает кто именно ему шлёт запрос и отправляет его в очередь возвращая STATUS_PENDING. Есстественно утилита подвисает так как она ведь и должна ответить на него. Может кто вкурсе что я делаю не так ? Я себе представлял что CreateFile посылает единственный запрос IRP_MJ_CREATE...
После регистрации устройства, user mode прога может сделать CreateFile(), который в ядре превращается в IRP_MJ_CREATE. После открытия устройства прога делает ReadFile(), WriteFile() или DeviceIOControl(). Все эти вызовы становятся IRP в ядре. Теория такая - в ядре всё асинхронно - приходит IRP и ты его обслуживаешь сразу или запихиваешь в Cancel Safe Queue и помечаешь pending. В проге ты можешь делать blocking read/write или overlapped IO. По поводу IRP_MJ_CREATE - выложи код - у тебя где-то косяк.
Код (Text): UNICODE_STRING symLinkName; UNICODE_STRING device_name; UCHAR drive_letter; LARGE_INTEGER drive_size; #pragma code_seg("INIT") NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status; PDEVICE_EXTENSION device_extension; PDEVICE_OBJECT device_object; RtlInitUnicodeString(&device_name, DEVICE_DEVICE_NAME); status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &device_name, FILE_DEVICE_DISK, 0, FALSE, &device_object ); if (!NT_SUCCESS(status)) { KdPrint(("Error creating device \n")); return status; } device_object->Flags |= DO_DIRECT_IO; device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; device_extension->list_cnt = 0; InitializeListHead(&device_extension->list_head); KeInitializeSpinLock(&device_extension->list_lock); KdPrint(("Device created \n")); /* *** SYMBOLIC LINK INITIALIZATION *** */ drive_letter = 0; drive_size.QuadPart = 0; RtlInitUnicodeString(&symLinkName, DEVICE_SYMLINK_NAME); status = IoCreateSymbolicLink(&symLinkName,&device_name); if (!NT_SUCCESS(status)) { KdPrint(("Error creating SymbolicLink \n")); IoDeleteDevice(device_object); return status; } KdPrint(("SymbolicLink created \n")); 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; } #pragma code_seg("PAGE") VOID FileDiskUnload ( IN PDRIVER_OBJECT DriverObject ) { PDEVICE_OBJECT device_object; PDEVICE_EXTENSION device_extension; PAGED_CODE(); device_object = DriverObject->DeviceObject; device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; if (drive_letter != 0) { DriveLetterDelete(); } IoDeleteSymbolicLink(&symLinkName); IoDeleteDevice(device_object); } NTSTATUS FileDiskCreateClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { KdPrint(("Create/Close \n")); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } #pragma code_seg() NTSTATUS FileDiskReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; KdPrint(("FileDisk: Read/Write \n")); // status = IRPAddToQue(DeviceObject,Irp); status = STATUS_INVALID_DEVICE_REQUEST; if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return status; } По поводу того что всё превращается в IRP я знаю. Но как тогда выходит данный результат? Вот код который исполняется в утилите при нажатии кнопки: Код (Text): Var Handle : Integer; begin Handle:=CreateFile( PChar('\\.\\symFileDisk'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, Open_Existing, 0, 0); FileClose(Handle); end; И всё, больше абсолютно ничего... вот что в этот момент показывает Compuware Monitor под которым запущен драйвер: Код (Text): Monitor Driver started successfully. 71.219 Default Device created 71.219 Default SymbolicLink created 78.219 Default FileDisk: IoControlCode 0x70000 78.219 Default FileDisk: Read/Write 78.219 Default FileDisk: IoControlCode 0x70000 78.219 Default FileDisk: Read/Write 78.219 Default FileDisk: IoControlCode 0x74804 78.219 Default FileDisk: IoControlCode 0x70024 78.219 Default FileDisk: IoControlCode 0x70000 78.219 Default FileDisk: IoControlCode 0x7405c 78.219 Default FileDisk: IoControlCode 0x74804
Только что попытался изменить тип устройства вместо FILE_DEVICE_DISK поставил FILE_DEVICE_UNKNOWN. При CreateFile() и CloseFile() отрабатывает как и нужно именно IRP_MJ_CREATE и IRP_MJ_CLOSE. Но мне то нужен именно диск... Непонятно както, ведь даже если указан FILE_DEVICE_DISK то я всёравно обращаюсь к нему как к файлу и не запрашиваю никаких IOCTL_DISK_GET_DRIVE_GEOMETRY и тп. :/
xneo, IoCreateDevice(FILE_DEVICE_UNKNOWN) даёт тебе устройство для внутреннего использования. То есть, ты сам решаешь что и как ты будешь принимать и посылать. IoCreateDevice(FILE_DEVICE_DISK) регистрирует диск и ты обязан реализовать всё что требует MS спецификация, а иначе это не будет работать как диск.
С другой стороны если это неизбежно, я могу создать в драйвере 2 устройства ? Первое-диск, второе-unknown... и посылая запросы второму забирать IRP из очереди первого? Просто я себе смутно представляю как ещё можно просто передать данные от драйвера приложению и обратно.
Енто, обработать все IRP запросы тебе всё равно придётся, а вот про смешивание... Обычно для этого регистрируется второе устройство.
Ребят, посмотрите пожалуйста... За стиль кода сильно не бейте Регистрируется 2 устройства... 1-FILE_DEVICE_DISK 2-FILE_DEVICE_UNKNOWN Первое принимает запросы и сохраняет в очередь возвращая STATUS_PENDING, второе используется для связи с утилитой которая по IOCTL_DISK_GET_IRP забирает запросы из очереди и по IOCTL_DISK_SET_IRP отвечает на них. Забирает пару запросов, отвечает на них... а потом BSOD. Иногда кричит в BSOD про страничную память. Код (Text): #include <ntddk.h> #include <ntdddisk.h> #define DEVICE_DISK_NAME L"\\Device\\eStorageDisk" #define DEVICE_CONTROL_NAME L"\\Device\\eStorageCtrl" #define DEVICE_SYMLINK_NAME L"\\??\\eStorageCtrlSym" #define IOCTL_DISK_ASSIGN_LETTER CTL_CODE(FILE_DEVICE_DISK, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_DISK_GET_IRP CTL_CODE(FILE_DEVICE_DISK, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_DISK_SET_IRP CTL_CODE(FILE_DEVICE_DISK, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) const MaxListQue = 32; const IrpBufferSize = 8192; const Dev_Type_Storage = 1; const Dev_Type_Control = 2; // ***************** S T R U C T U R E S ************************** typedef struct _DEVICE_EXTENSION { int device_type; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; typedef struct _LAST_REQUEST { BOOLEAN empty; PIRP irp; PLIST_ENTRY request; PIO_STACK_LOCATION stack; } LAST_REQUEST, *PLAST_REQUEST; #pragma pack (1) typedef struct _IRP_GET_ITEM { UCHAR major_func; UCHAR minor_func; ULONG iocode; LONGLONG rw_data_offset; ULONG rw_data_length; UCHAR buffer[8192]; } IRP_GET_ITEM, *PIRP_GET_ITEM; typedef struct _IRP_SET_ITEM { ULONG status; ULONG data_length; UCHAR buffer[8192]; } IRP_SET_ITEM, *PIRP_SET_ITEM; #pragma pack (4) // ********************* V A R I A B L E S ************************** UNICODE_STRING symLinkName; UNICODE_STRING device_stor_name; UNICODE_STRING device_ctrl_name; UCHAR drive_letter; LIST_ENTRY list_head; KSPIN_LOCK list_lock; LAST_REQUEST last_request; int list_cnt; int connects_cnt; NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); VOID DriverUnload ( IN PDRIVER_OBJECT DriverObject ); NTSTATUS OnCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS OnClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS OnReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS OnDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); NTSTATUS IRPAddToQue ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); void DriveLetterDelete(); #pragma code_seg("INIT") NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status; PDEVICE_OBJECT device_stor; PDEVICE_OBJECT device_ctrl; PDEVICE_EXTENSION device_extension; RtlInitUnicodeString(&device_stor_name, DEVICE_DISK_NAME); status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &device_stor_name, FILE_DEVICE_DISK, 0, FALSE, &device_stor); if (!NT_SUCCESS(status)) { KdPrint(("Error creating device \n")); IoDeleteDevice(device_stor); return status; } RtlInitUnicodeString(&device_ctrl_name, DEVICE_CONTROL_NAME); status = IoCreateDevice( DriverObject, sizeof(DEVICE_EXTENSION), &device_ctrl_name, FILE_DEVICE_UNKNOWN, 0, FALSE, &device_ctrl); if (!NT_SUCCESS(status)) { KdPrint(("Error creating device \n")); IoDeleteDevice(device_stor); IoDeleteDevice(device_ctrl); return status; } device_stor->Flags |= DO_BUFFERED_IO; device_ctrl->Flags |= DO_BUFFERED_IO; device_extension = (PDEVICE_EXTENSION) device_stor->DeviceExtension; device_extension->device_type = Dev_Type_Storage; device_extension = (PDEVICE_EXTENSION) device_ctrl->DeviceExtension; device_extension->device_type = Dev_Type_Control; list_cnt = 0; connects_cnt = 0; last_request.empty = TRUE; InitializeListHead(&list_head); KeInitializeSpinLock(&list_lock); KdPrint(("Device created \n")); /* *** SYMBOLIC LINK INITIALIZATION *** */ drive_letter = 0; RtlInitUnicodeString(&symLinkName, DEVICE_SYMLINK_NAME); status = IoCreateSymbolicLink(&symLinkName,&device_ctrl_name); if (!NT_SUCCESS(status)) { KdPrint(("Error creating SymbolicLink \n")); IoDeleteDevice(device_stor); IoDeleteDevice(device_ctrl); return status; } KdPrint(("SymbolicLink created \n")); DriverObject->MajorFunction[IRP_MJ_CREATE] = OnCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = OnClose; DriverObject->MajorFunction[IRP_MJ_READ] = OnReadWrite; DriverObject->MajorFunction[IRP_MJ_WRITE] = OnReadWrite; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OnDeviceControl; DriverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; } #pragma code_seg("PAGE") VOID DriverUnload ( IN PDRIVER_OBJECT DriverObject ) { PDEVICE_OBJECT device_object, next_device_object; PAGED_CODE(); KdPrint(("Unload \n")); if (drive_letter != 0) { DriveLetterDelete(); } KdPrint(("Delete link \n")); IoDeleteSymbolicLink(&symLinkName); device_object = DriverObject->DeviceObject; while (device_object) { KdPrint(("Delete device \n")); next_device_object = device_object->NextDevice; IoDeleteDevice(device_object); device_object = next_device_object; } } NTSTATUS OnCreate ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; KdPrint(("Create %#x \n",device_extension->device_type)); if (device_extension->device_type == Dev_Type_Control) { connects_cnt++; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS OnClose ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; KdPrint(("Close %#x \n",device_extension->device_type)); if (device_extension->device_type == Dev_Type_Control) { connects_cnt--; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } #pragma code_seg() NTSTATUS OnReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS status; KdPrint(("FileDisk: Read/Write \n")); status = IRPAddToQue(DeviceObject,Irp); if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return status; } NTSTATUS OnDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; PIO_STACK_LOCATION io_stack; NTSTATUS status; UNICODE_STRING ustr; ANSI_STRING astr; PIRP_GET_ITEM airp_item; PIRP_SET_ITEM sirp_item; ULONG asize; ULONG dsize; PUCHAR buffer; char dl[7] = "\\??\\ : "; device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; io_stack = IoGetCurrentIrpStackLocation(Irp); status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Information = 0; switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_DISK_ASSIGN_LETTER: { status = STATUS_INVALID_PARAMETER; if (io_stack->Parameters.DeviceIoControl.InputBufferLength == 1) { dl[6] = 0; RtlCopyMemory(&dl[4],Irp->AssociatedIrp.SystemBuffer,1); if ((drive_letter == 0)&&(dl[4] != 0)) { KdPrint(("FileDisk: ASSIGN LETTER \n")); RtlInitAnsiString(&astr,(LPCSTR) &dl); RtlAnsiStringToUnicodeString(&ustr,&astr, TRUE); KdPrint(((PCHAR) &dl,'\n')); if (NT_SUCCESS(IoCreateSymbolicLink(&ustr, &device_stor_name))) { drive_letter = dl[4]; status = STATUS_SUCCESS; } RtlFreeUnicodeString(&ustr); } if ((drive_letter != 0)&&(dl[4] == 0)) { KdPrint(("FileDisk: DELETE LETTER \n")); DriveLetterDelete(); status = STATUS_SUCCESS; } } break; } case IOCTL_DISK_GET_IRP: { if (last_request.empty) { if (last_request.request = ExInterlockedRemoveHeadList(&list_head,&list_lock)) { last_request.irp = CONTAINING_RECORD(last_request.request, IRP, Tail.Overlay.ListEntry); last_request.stack = IoGetCurrentIrpStackLocation(last_request.irp); last_request.empty = FALSE; } } if (last_request.empty == FALSE) { airp_item = Irp->AssociatedIrp.SystemBuffer; airp_item->major_func = last_request.stack->MajorFunction; airp_item->minor_func = last_request.stack->MinorFunction; airp_item->iocode = last_request.stack->Parameters.DeviceIoControl.IoControlCode; airp_item->rw_data_offset = last_request.stack->Parameters.Read.ByteOffset.QuadPart; airp_item->rw_data_length = last_request.stack->Parameters.Read.Length; KdPrint(("Get Irp IOCode=%#x \n",last_request.stack->Parameters.DeviceIoControl.IoControlCode)); asize = sizeof(IRP_GET_ITEM) - IrpBufferSize; dsize = 0; if (last_request.stack->MajorFunction == IRP_MJ_WRITE) { dsize = last_request.stack->Parameters.Write.Length; asize = asize + dsize; } if (io_stack->Parameters.DeviceIoControl.OutputBufferLength < asize) { status = STATUS_BUFFER_TOO_SMALL; } else { if (dsize > 0) { // RtlCopyMemory(&airp_item->buffer,last_request.irp->AssociatedIrp.SystemBuffer,dsize); } Irp->IoStatus.Information = asize; status = STATUS_SUCCESS; } } else { status = STATUS_SUCCESS; } break; } case IOCTL_DISK_SET_IRP: { if (io_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(IRP_SET_ITEM) - IrpBufferSize) { KdPrint(("Buffer too small \n")); status = STATUS_BUFFER_TOO_SMALL; break; } sirp_item = Irp->AssociatedIrp.SystemBuffer; if (sirp_item->data_length+sizeof(IRP_SET_ITEM)-IrpBufferSize > io_stack->Parameters.DeviceIoControl.InputBufferLength) { KdPrint(("Wrong Size \n")); status = STATUS_INVALID_PARAMETER; break; } if (last_request.empty == FALSE) { KdPrint(("Set Irp Status=%#x IOCode=%#x \n",sirp_item->status,sirp_item->data_length)); last_request.irp->IoStatus.Status = sirp_item->status; last_request.irp->IoStatus.Information = sirp_item->data_length; if (sirp_item->data_length>0) { KdPrint(("Assign buffer \n")); RtlCopyMemory(last_request.irp->AssociatedIrp.SystemBuffer, &sirp_item->buffer, sirp_item->data_length); } IoCompleteRequest(last_request.irp, IO_NO_INCREMENT); last_request.empty = TRUE; list_cnt--; status = STATUS_SUCCESS; } else { KdPrint(("Que is empty \n")); status = STATUS_INVALID_PARAMETER; } break; } case IOCTL_DISK_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY2: case IOCTL_DISK_GET_DRIVE_GEOMETRY: case IOCTL_DISK_GET_LENGTH_INFO: case IOCTL_DISK_GET_PARTITION_INFO: case IOCTL_DISK_GET_PARTITION_INFO_EX: case IOCTL_DISK_IS_WRITABLE: case IOCTL_DISK_MEDIA_REMOVAL: case IOCTL_STORAGE_MEDIA_REMOVAL: case IOCTL_DISK_SET_PARTITION_INFO: case IOCTL_DISK_VERIFY: { status = IRPAddToQue(DeviceObject,Irp); break; } } if (status != STATUS_PENDING) { Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return status; } NTSTATUS IRPAddToQue ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; Irp->IoStatus.Information = 0; if (device_extension->device_type != Dev_Type_Storage) { KdPrint(("FileDisk: Cant add to Que control packet \n")); return STATUS_INVALID_DEVICE_REQUEST; } if ((list_cnt >= MaxListQue) || (connects_cnt <= 0)) { KdPrint(("FileDisk: Que add error \n")); return STATUS_NO_MEDIA_IN_DEVICE; } else { list_cnt++; KdPrint(("FileDisk: Added to Que, Que size = %#x\n",list_cnt)); IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &list_head, &Irp->Tail.Overlay.ListEntry, &list_lock); return STATUS_PENDING; } } void DriveLetterDelete() { UNICODE_STRING ustr; ANSI_STRING astr; char dl[7] = "\\??\\ : "; dl[4] = drive_letter; dl[6] = 0; RtlInitAnsiString(&astr,(LPCSTR) &dl); RtlAnsiStringToUnicodeString(&ustr,&astr, TRUE); KdPrint(((PCHAR) &dl,'\n')); if (NT_SUCCESS(IoDeleteSymbolicLink(&ustr))) { drive_letter = 0; } RtlFreeUnicodeString(&ustr); }
я могу посоветовать заглянуть на сайт либо Freed0m.org (там есть как раз ваш велосипед) или http://www.acc.umu.se/~bosse/ там тоже много по теме.