How do I get a file handle during a IRP_MJ_SET_INFORMATION?

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 );
}

>(specifically I need to use ZwQueryInformationFile, ZwReadFile,
ZwSetInformationFile,

ZwQueryDirectoryFile; I know I could use directly IRP but it would be a
nightmare).

Just assemble your own IRPs instead of these functions.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Thanks for the answer.

I know I can build my own IRPs, but it would be very complex since I have
to copy whole directories instead of a simple rename.

Thus, I was hoping there is a better way. I have seen that the function
ObOpenObjectByPointer works successfully inside a IRP_MJ_CREATE.

>(specifically I need to use ZwQueryInformationFile, ZwReadFile,
ZwSetInformationFile,
>ZwQueryDirectoryFile; I know I could use directly IRP but it would be a
nightmare).

Just assemble your own IRPs instead of these functions.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

I too, subscribe to Max’s opinion. It is not a such a nightmare as you might
think.
The only thing which I want to add, from my own experience, it is advisable
to write those
functions in a library like manner ( FsQueryInformationFile() … and so
on), in a clear and
documented way. This way in time you will build a very helpfull library in
time, which you
(or the company) will be able to reuse at any point in time. It is a gain in
the long run.

Dan

----- Original Message -----
From: “Francesco”
Newsgroups: ntfsd
To: “Windows File Systems Devs Interest List”
Sent: Sunday, January 09, 2005 8:47 PM
Subject: Re:[ntfsd] How do I get a file handle during a
IRP_MJ_SET_INFORMATION?

> Thanks for the answer.
>
> I know I can build my own IRPs, but it would be very complex since I have
> to copy whole directories instead of a simple rename.
>
> Thus, I was hoping there is a better way. I have seen that the function
> ObOpenObjectByPointer works successfully inside a IRP_MJ_CREATE.
>
>
>
>>>(specifically I need to use ZwQueryInformationFile, ZwReadFile,
>> ZwSetInformationFile,
>>>ZwQueryDirectoryFile; I know I could use directly IRP but it would be a
>> nightmare).
>>
>> Just assemble your own IRPs instead of these functions.
>>
>> Maxim Shatskih, Windows DDK MVP
>> StorageCraft Corporation
>> xxxxx@storagecraft.com
>> http://www.storagecraft.com
>>
>>
>
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@rdsor.ro
> To unsubscribe send a blank email to xxxxx@lists.osr.com