There is an easy way to get the file size, if that’s all you need:
‘FsRtlGetFileSize’. All he does (I think) is roll up a query information
irp and send it down on your behalf (he may be smart enought to look in the
FCB header as an optimization, but I’m not sure). You’ll find the prototype
for this function in ntifs.h.
I don’t know if this function helps you are not, but if you are
attempting to get the size of an already opened file (and you are currently
using Zw routines to accomplish this), it should save you some headaches.
Causing the driver stack to be arbitrarily reentered can cause hangs and
deadlocks (which can be difficult to recreate at times!). As a general
rule, I think it is best to only send irp’s downward from your spot in the
driver stack.
If you are querying a file that is not already open, then you will
have to use ZwCreate (and reenter the stack), again, unless you really know
what you are doing (and can roll you own create irp). There is one
exception, if you are trying to open the target of another open (i.e. you
need to open the file that is the target of an open in your create dispatch
handler) you can hijack the irp that was sent to your create and use it to
open the file. You can then do what you need, cleanup and close the file
and then ‘re-send’ the same irp to carry out its intended task. There are
some small gotcha’s involved, but it doesn’t sound like you need to do this
so I won’t elaborate.
I believe the FsRtlGetFileSize only gets the logical file size. If
you need the allocation size, you will want to roll your own query
information irp. I’ve attached some code that works for me. If the code
has any flaws (it may, I’m relatively new to this) I’m sure someone on the
list will point them out. Note that the completion routine is generic, and
for this, you won’t need the bit that unmaps the mdl.
-Joel
NTSTATUS QmGetOpenFileInformation(PFILE_OBJECT pFile, PDEVICE_OBJECT
pVolDev, FILE_INFORMATION_CLASS InfoClass, void *pBuffer, int nBufferLength)
{
KEVENT event;
IO_STATUS_BLOCK stat;
PIRP pIrp;
PIO_STACK_LOCATION pStack;
NTSTATUS ntRet;
PFSRTL_COMMON_FCB_HEADER pFCB;
__try
{
__try
{
//initialize event to signal completion
KeInitializeEvent(&event, SynchronizationEvent,
FALSE);
//allocate a new irp
pIrp = IoAllocateIrp(pVolDev->StackSize, FALSE);
//set a completion routine to free the irp
IoSetCompletionRoutine(pIrp, QmDefaultComplete, 0,
TRUE, TRUE, TRUE);
//setup the irp
pIrp->UserEvent = &event;
pIrp->AssociatedIrp.SystemBuffer = pBuffer;
pIrp->UserIosb = &stat;
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->Tail.Overlay.OriginalFileObject = pFile;
pIrp->RequestorMode = KernelMode;
//or in a ‘synchronous’ flag so FASTFAT doesn’t puke
pIrp->Flags |= IRP_SYNCHRONOUS_API;
//Set up the I/O stack location.
pStack = IoGetNextIrpStackLocation(pIrp);
pStack->MajorFunction = IRP_MJ_QUERY_INFORMATION;
pStack->DeviceObject = pVolDev;
pStack->FileObject = pFile;
pStack->Parameters.QueryFile.Length = nBufferLength;
pStack->Parameters.QueryFile.FileInformationClass =
InfoClass;
//Send it to the FSD
ntRet = IoCallDriver(pVolDev, pIrp);
if (ntRet == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive,
KernelMode, TRUE, NULL);
}
ntRet = stat.Status;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DEFAULT_EXCEPTION_HANDLER(“QmGetOpenFileInformation”);
ntRet = GetExceptionCode();
}
}
__finally
{
}
//report the result
return ntRet;
}
//completion routine which simply frees up a driver created IRP which
//was sent to some other driver
NTSTATUS QmDefaultComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PVOID Context)
{
PVOID pPtr;
PMDL pMdl;
*pIrp->UserIosb = pIrp->IoStatus;
//if there is an MDL, we must unmap/unlock it
pMdl = pIrp->MdlAddress;
while (pMdl != NULL)
{
MmUnlockPages(pMdl);
pMdl = pMdl->Next;
}
if (pIrp->MdlAddress != NULL)
{
IoFreeMdl(pIrp->MdlAddress);
}
// Set the user event - wakes up the mainline code doing this.
KeSetEvent(pIrp->UserEvent, 0, FALSE);
// Free the IRP now that we are done with it.
IoFreeIrp(pIrp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
-----Original Message-----
From: Ho Mun Chuen [mailto:xxxxx@pmail.ntu.edu.sg]
Sent: Wednesday, October 04, 2000 6:06 AM
To: File Systems Developers
Subject: [ntfsd] diectory control and winzip
i am writing an encryption filter driver and has encountered a problem when
executing Winzip. as my driver will append a footer to a file, i have
intercepted the IRP_MJ_SET_INFORMATION and the IRP_MJ_QUERY_INFORMATION irps
and change the info according to reflect no footer. however, as Winzip uses
the IRP_MJ_DIRECTORY_CONTROL irp, i have attempted to change the info as
well. i will use Zw commands to create, query and then close the file
(through my driver) to get the original size of the file without the footer
and return the info. however, the ZwClose command does not result in a
IRP_MJ_CLOSE and causes this command to “hang”.
anyone has a better way to query info?
Ho Mun Chuen
xxxxx@pmail.ntu.edu.sg
@@ “Not everything that counts can be counted;
<” )~ and not everything that can be counted counts"
//\ … Albert Einstein
You are currently subscribed to ntfsd as: xxxxx@ntpsoftware.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)