Hi all,
I am writing a filter driver that aims to replace the move operation
with a copy and a following deletion. Basically I intercept the
IRP_MJ_SET_INFORMATION irp and I would like to get a handle to the file,
which is supposed to be renamed, in order to use ZwXXX functions
(specifically I need to use ZwQueryInformationFile, ZwReadFile,
ZwSetInformationFile, ZwQueryDirectoryFile; I know I could use directly
IRP but it would be a nightmare).
I see the DDK provides a function ObOpenObjectByPointer, that opens a
handle given a file object. In fact this function works successfully if
called during a IRP_MJ_CREATE, but comes to a deadlock when used inside
the IRP_MJ_SET_INFORMATION.
I guess that the ZwSetInformationFile locks the file and thus the
ObOpenObjectByPointer stops waiting for a lock that hangs the process.
I tried calling ObOpenObjectByPointer both inside the irp handler and a
work thread.
I tried also calling KeStackAttachProcess before ObOpenObjectByPointer
but nothing changes (actually I am not sure I am attaching to the right
process).
Does anyone have a solution? Following is the code I am using.
Thanks, Francesco
typedef struct {
PFilter filter;
PFILE_OBJECT fileObject;
PFILE_RENAME_INFORMATION renameInformation;
PKEVENT waitRename;
PIO_WORKITEM workItem;
} RenameCtx, *PRenameCtx;
VOID
renameWork(PFilter filter, PFILE_OBJECT fileObject,
PFILE_RENAME_INFORMATION renameInformation,
PKEVENT waitRename) {
FILE_STANDARD_INFORMATION standardInformation;
UCHAR emptyBuf[512];
HANDLE file;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
LARGE_INTEGER writeSoFar;
ULONG blockSize;
KAPC_STATE apcState;
DbgBreakPoint();
* KeStackAttachProcess(SystemProcess, &apcState);
status = ObOpenObjectByPointer(fileObject, 0, NULL, FILE_READ_DATA,
NULL, KernelMode, &file);
KeUnstackDetachProcess(&apcState);
* if (!NT_SUCCESS( status )) {
KDPRINT(“CLEANUP: cannot open object by pointer %p because
%s\n”, fileObject,
OsrNTStatusToString(status));
}
if (waitRename != NULL)
KeSetEvent(waitRename, IO_NO_INCREMENT, FALSE);
}
VOID
renameWorkRoutine(PDEVICE_OBJECT deviceObject, PVOID context) {
PRenameCtx renameCtx = (PRenameCtx) context;
//DbgBreakPoint();
renameWork(renameCtx->filter, renameCtx->fileObject,
renameCtx->renameInformation,
renameCtx->waitRename);
IoFreeWorkItem(renameCtx->workItem);
ExFreePool(renameCtx);
}
NTSTATUS
driverSetInformation (PDEVICE_OBJECT deviceObject, PIRP irp) {
PIO_STACK_LOCATION irpStack;
PFilter filter;
PFILE_DISPOSITION_INFORMATION dispositionInformation;
PFILE_RENAME_INFORMATION renameInformation;
NTSTATUS status;
HANDLE file;
KEVENT waitRename;
PRenameCtx renameCtx;
irpStack = IoGetCurrentIrpStackLocation( irp );
if (irpStack->Parameters.SetFile.FileInformationClass ==
FileDispositionInformation) {
filter = deviceObject->DeviceExtension;
dispositionInformation = (PFILE_DISPOSITION_INFORMATION)
irp->AssociatedIrp.SystemBuffer;
if (dispositionInformation->DeleteFile &&
!FileMap_has(filter->cleanupFiles, irpStack->FileObject))
FileMap_add(filter->cleanupFiles, irpStack->FileObject);
else if (!dispositionInformation->DeleteFile &&
FileMap_has(filter->cleanupFiles, irpStack->FileObject))
FileMap_remove(filter->cleanupFiles, irpStack->FileObject);
}
if (irpStack->Parameters.SetFile.FileInformationClass ==
FileRenameInformation) {
renameInformation = (PFILE_RENAME_INFORMATION)
irp->AssociatedIrp.SystemBuffer;
KDPRINT(“rename file to ‘%S’”, renameInformation->FileName);
DbgBreakPoint();
KeInitializeEvent( &waitRename,
NotificationEvent,
FALSE );
renameCtx = ExAllocatePoolWithTag(NonPagedPool,
sizeof(RenameCtx), FSCARE_POOL_TAG);
if (renameCtx == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
renameCtx->workItem = IoAllocateWorkItem(deviceObject);
if ( renameCtx->workItem == NULL ) {
ExFreePool(renameCtx);
return STATUS_INSUFFICIENT_RESOURCES;
}
renameCtx->filter = filter;
renameCtx->fileObject = irpStack->FileObject;
renameCtx->waitRename = &waitRename;
renameCtx->renameInformation = renameInformation;
KDPRINT(“fscare: process %i(%S) is renaming file ‘%wZ’ fd
%p\n”, PsGetCurrentProcessId(),
&irpStack->FileObject->FileName );
* SystemProcess = IoGetCurrentProcess();
* IoQueueWorkItem(renameCtx->workItem, renameWorkRoutine,
DelayedWorkQueue, renameCtx);
KeWaitForSingleObject( &waitRename, Executive, KernelMode,
FALSE, NULL );
}
return driverDefaultDispatch( deviceObject, irp );
}