Hi again,
Sorry, that bother you with my problem.
I have created a small filter, which does nothing, except…
prevents the system from shutting down and the delayed
write thread from flushing buffers !!!
I really do not understand what’s wrong in my code.
This code is below. All fast I/O routines are same as
FastIoCall here, except DetachDevice and QueryOpen.
Could you, please, check it, if you have a time.
Thanks a lot in advance.
Leonid.
//
// Definitions
//
typedef struct _DEVICE_EXTENSION {
ULONG DeviceType;
PDEVICE_OBJECT TargetDevice;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define DEVICE_TYPE_CONTROL_DEVICE 1
#define DEVICE_TYPE_FILE_SYSTEM_FILTER 2
#define DEVICE_TYPE_LOGICAL_VOLUME_FILTER 3
#define I2K_NATIVE_DEVICE_NAME L"\I2kfilt"
#define I2K_DOS_DEVICE_NAME L"\DosDevices\I2KFILT"
#define FILE_DEVICE_I2KFILT 0x9b00
//
// Global data
//
FAST_IO_DISPATCH
I2kFastIoDispatch = {
sizeof(FAST_IO_DISPATCH),
I2kFastIoCheckIfPossible,
I2kFastIoRead,
I2kFastIoWrite,
I2kFastIoQueryBasicInfo,
I2kFastIoQueryStandardInfo,
I2kFastIoLock,
I2kFastIoUnlockSingle,
I2kFastIoUnlockAll,
I2kFastIoUnlockAllByKey,
I2kFastIoDeviceControl,
NULL, // I2kAcquireFileForNtCreateSection,
NULL, // I2kReleaseFileForNtCreateSection,
I2kFastIoDetachDevice,
I2kFastIoQueryNetworkOpenInfo,
NULL, // I2kAcquireForModWrite,
I2kMdlRead,
I2kMdlReadComplete,
I2kPrepareMdlWrite,
I2kMdlWriteComplete,
I2kFastIoReadCompressed,
I2kFastIoWriteCompressed,
I2kMdlReadCompleteCompressed,
I2kMdlWriteCompleteCompressed,
I2kFastIoQueryOpen,
NULL, // I2kReleaseForModWrite,
NULL, // I2kAcquireForCcFlush,
NULL, // I2kReleaseForCcFlush
};
PDRIVER_OBJECT I2kDriverObject = NULL;
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION deviceExtension;
UNICODE_STRING deviceName;
UNICODE_STRING deviceLink;
NTSTATUS status;
ULONG i;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = I2kIrpDispatch;
}
DriverObject->FastIoDispatch = &I2kFastIoDispatch;
RtlInitUnicodeString(&deviceName, I2K_NATIVE_DEVICE_NAME);
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&deviceName,
FILE_DEVICE_FILE_SYSTEM,
0,
FALSE,
&deviceObject
);
if (!NT_SUCCESS(status)) {
return(status);
}
deviceExtension = deviceObject->DeviceExtension;
deviceExtension->DeviceType = DEVICE_TYPE_CONTROL_DEVICE;
RtlInitUnicodeString(&deviceLink, I2K_DOS_DEVICE_NAME);
status = IoCreateSymbolicLink(&deviceLink, &deviceName);
if (!NT_SUCCESS(status)) {
IoDeleteSymbolicLink(&deviceLink);
IoDeleteDevice(deviceObject);
}
I2kDriverObject = DriverObject;
IoRegisterFsRegistrationChange(DriverObject, I2kFsRegistrationChange);
return(status);
}
VOID
I2kFsRegistrationChange (
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN FsActive
)
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS status;
if (DeviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM) {
return;
}
if (FsActive) {
I2kCreateFilterDevice(
DeviceObject,
DEVICE_TYPE_FILE_SYSTEM_FILTER
);
}
}
NTSTATUS
I2kIrpDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
switch (DeviceExtension->DeviceType) {
case DEVICE_TYPE_CONTROL_DEVICE:
status = I2kControlDeviceDispatch(DeviceObject, Irp);
break;
case DEVICE_TYPE_FILE_SYSTEM_FILTER:
status = I2kFileSystemFilterDispatch(DeviceObject, Irp);
break;
case DEVICE_TYPE_LOGICAL_VOLUME_FILTER:
status = I2kLogicalVolumeFilterDispatch(DeviceObject, Irp);
break;
default:
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
return(status);
}
NTSTATUS
I2kControlDeviceDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(Irp->IoStatus.Status);
}
NTSTATUS
I2kFileSystemFilterDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_OBJECT deviceObject;
KEVENT event;
NTSTATUS status;
if (currentIrpStack->MajorFunction != IRP_MJ_FILE_SYSTEM_CONTROL ||
currentIrpStack->MinorFunction != IRP_MN_MOUNT_VOLUME) {
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(DeviceExtension->TargetDevice, Irp));
}
deviceObject = currentIrpStack->Parameters.MountVolume.Vpb->RealDevice;
if (deviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(DeviceExtension->TargetDevice, Irp));
}
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, I2kFileSystemFilterComplete, &event, TRUE,
TRUE, TRUE);
status = IoCallDriver(DeviceExtension->TargetDevice, Irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = Irp->IoStatus.Status;
}
if (NT_SUCCESS(status)) {
I2kCreateFilterDevice(
deviceObject->Vpb->DeviceObject,
DEVICE_TYPE_LOGICAL_VOLUME_FILTER
);
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(status);
}
NTSTATUS
I2kFileSystemFilterComplete (
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
)
{
PKEVENT event = (PKEVENT) Context;
KeSetEvent(event, 0, FALSE);
return(STATUS_MORE_PROCESSING_REQUIRED);
}
NTSTATUS
I2kLogicalVolumeFilterDispatch (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return(IoCallDriver(DeviceExtension->TargetDevice, Irp));
}
NTSTATUS
I2kCreateFilterDevice (
IN PDEVICE_OBJECT TargetDevice,
IN ULONG DeviceType
)
{
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT stackTopObject;
NTSTATUS status;
status = IoCreateDevice(
I2kDriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
TargetDevice->DeviceType,
TargetDevice->Characteristics,
FALSE,
&deviceObject
);
if (!NT_SUCCESS(status)) {
return(status);
}
deviceExtension = deviceObject->DeviceExtension;
deviceExtension->DeviceType = DeviceType;
stackTopObject = IoAttachDeviceToDeviceStack(deviceObject,
TargetDevice);
if (!stackTopObject) {
IoDeleteDevice(deviceObject);
return(STATUS_NO_SUCH_DEVICE);
}
deviceExtension->TargetDevice = stackTopObject;
deviceObject->Flags |= (stackTopObject->Flags & (DO_BUFFERED_IO |
DO_DIRECT_IO));
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return(status);
}
VOID
I2kDeleteFilterDevice (
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
IoDetachDevice(DeviceExtension->TargetDevice);
IoDeleteDevice(DeviceObject);
}
BOOLEAN
I2kFastIoCall (
IN OUT OTHER_PARAMETERS OtherParameters,
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT deviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
BOOLEAN result = FALSE;
deviceObject = ((PDEVICE_EXTENSION)
DeviceObject->DeviceExtension)->TargetDevice;
if (deviceObject == NULL) {
return(result);
}
fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
if (fastIoDispatch &&
fastIoDispatch->SizeOfFastIoDispatch >
FIELD_OFFSET(FAST_IO_DISPATCH, FastIoCall) &&
fastIoDispatch->FastIoCall) {
result = (fastIoDispatch->FastIoCall)(
OtherParameters,
deviceObject
);
}
return(result);
}
VOID
I2kFastIoDetachDevice (
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice
)
{
PDEVICE_EXTENSION deviceExtension = SourceDevice->DeviceExtension;
I2kDeleteFilterDevice(SourceDevice);
}
BOOLEAN
I2kFastIoQueryOpen (
IN PIRP Irp,
OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation,
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_OBJECT deviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PIO_STACK_LOCATION currentIrpStack;
BOOLEAN result = FALSE;
deviceObject = ((PDEVICE_EXTENSION)
DeviceObject->DeviceExtension)->TargetDevice;
if (deviceObject == NULL) {
return(result);
}
fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
if (fastIoDispatch &&
fastIoDispatch->SizeOfFastIoDispatch >
FIELD_OFFSET(FAST_IO_DISPATCH, FastIoQueryOpen) &&
fastIoDispatch->FastIoQueryOpen) {
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
currentIrpStack->DeviceObject = deviceObject;
result = (fastIoDispatch->FastIoQueryOpen)(
Irp,
NetworkInformation,
deviceObject
);
if (result == FALSE) {
currentIrpStack->DeviceObject = DeviceObject;
}
}
return(result);
}