RE: Pre-query information for IRP_MJ_CREATE with FILE_OPE- N_BY_FILEID

Svante,

Perhaps you don’t need to learn the ‘real’ name of the target.
Maybe you can just take control of the original irp where everything is
already set up for you.
You could let the irp pass through, and then ‘cancel’ the create
with IoCancelFileOpen (IoCancelFileOpen essentially sends a cleanup and
close irp to the fsd) if you decide you shouldn’t let the user open it.
You may wish to alter the original irp do negate destructive side
effects. For example, you pass through an irp with an overwrite
disposition, then later discover that you have to cancel the create. Even
if you cancel the create, the file would still have been overwritten. To
the user, it would appear as if the file open was denied, but the
pre-existing target of the overwrite would be truncated. If you are facing
such a problem, then take a look at the routines I pasted below. These
routines are used to open the target of a create irp (actually, you can
redirect to open a different file if you want) by ‘hijacking’ the original
create irp. (DISCLAIMER: These routines have only been lightly used, so DO
NOT assume they are without bugs!). Perhaps you could come up with a
similar scheme.
An additional benefit of the ‘hijacking’ scheme is that it will not
cause the device stack to be reentered from the top as would ZwCreateFile.

Hope it helps

Joel

//local functions
void NrRestoreIrp(PIRP pIrp, PNRCREATE_CONTEXT pCtx);
NTSTATUS NrCreateComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PKEVENT pEvent);

/*
NON_REENTRANT CREATE:
This module implements a utility function that can be used to open the
target of a create
io before the FSD processes the create io. The assumption is that the
caller wishes to
figure out some information about the file being opened before it is
actually opened. The
function hijacks the original create irp, neuters it (removing any
destructive bits such
overwrite dispositions or delete on close semantics). The irps open file
object can then
be used by the caller to do whatever. The related close operation must be
called.
*/

NTSTATUS NrCreate(PDEVICE_OBJECT pFilter, PIRP pIrp,
/*optional*/PUNICODE_STRING pstrNewName, PNRCREATE_CONTEXT pCtx)
{
NTSTATUS ntRet;
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
PFILE_OBJECT pFile = pStack->FileObject;
KEVENT event;
PFSENT_FILTER_EXTENSION pExt = pFilter->DeviceExtension;

//this can only be called for a non-open file in create dispatch
ASSERT(pStack->MajorFunction == IRP_MJ_CREATE);
ASSERT(pFile->FsContext2 == NULL);
ASSERT(pFile->FileName.Length);

//save old settings in the context
pCtx->ulFoFlags = pFile->Flags;
pCtx->ulIrpFlags = pIrp->Flags;
pCtx->DesiredAccess =
pStack->Parameters.Create.SecurityContext->DesiredAccess;
pCtx->cDisposition = GET_DISPOSITION(pStack);
pCtx->strOldFileName = pFile->FileName;
pCtx->pRelatedFileObject = NULL;
pCtx->ulOptions = pStack->Parameters.Create.Options &
FILE_VALID_OPTION_FLAGS;

//after this point, the irp must be restored to its original state if
the
//create fails. Neuter the irp:
//change the requested disposition to a simple open
SET_DISPOSITION(pStack, FILE_OPEN);

//set options to ‘0’
pStack->Parameters.Create.Options &= ~FILE_VALID_OPTION_FLAGS;

//if there is a related file object, save it, then null the field.
//This function only supports fully qualified paths
if (pFile->RelatedFileObject != NULL)
{
pCtx->pRelatedFileObject = pFile->RelatedFileObject;
pFile->RelatedFileObject = NULL;
}

//change the filename to any new filename
if (pstrNewName)
{
pFile->FileName = *pstrNewName;
}

//change the file access to synchronize
pStack->Parameters.Create.SecurityContext->DesiredAccess = SYNCHRONIZE;

//copy the stack down
IoCopyCurrentIrpStackLocationToNext(pIrp);

//we will wait on this event to make the operation always synchonous
KeInitializeEvent(&event, NotificationEvent, FALSE);

//set a completion routine
IoSetCompletionRoutine(pIrp,
NrCreateComplete,
&event,
TRUE,
TRUE,
TRUE);

//pass the neutered irp down (do we need to synchonize access to the
extension?)
ntRet = IoCallDriver(pExt->pNextDevice, pIrp);

//force the io to be synchronous
if (ntRet == STATUS_PENDING)
{
//wait for the event that is signalled in our completion
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);

//get the real success code
ntRet = pIrp->IoStatus.Status;
}

//if the function failed
if (!NT_SUCCESS(ntRet))
{
//restore the irp to its original state
NrRestoreIrp(pIrp, pCtx);
}
return ntRet;
}

//restores a neutered irp to its original state. This function is called
//in NrClose and in NrCreate, if the file create fails to opent he file
void NrRestoreIrp(PIRP pIrp, PNRCREATE_CONTEXT pCtx)
{
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);

//restore the irp
pStack->Parameters.Create.SecurityContext->DesiredAccess =
pCtx->DesiredAccess;
SET_DISPOSITION(pStack, pCtx->cDisposition);
pStack->FileObject->Flags = pCtx->ulFoFlags;
pIrp->Flags = pCtx->ulIrpFlags;

//ntfs truncates the filename length to 1, To patch this
//behavior, we saved a copy of the original file name and
//restore it here. This also restores the original file
//name if any new file name was specified
pStack->FileObject->FileName = pCtx->strOldFileName;

//need to investigate if this is really safe to do. I need to do this
//to get this function to work with the lanman redirector (which leaves
//these fields pointing to someting). Check to be sure something does
not
//need to be dereferenced or something
pStack->FileObject->FsContext = pStack->FileObject->FsContext2 = NULL;

//restore the related file object if there was one
if (pCtx->pRelatedFileObject != NULL)
{
pStack->FileObject->RelatedFileObject = pCtx->pRelatedFileObject;
}

//restore the original create options
pStack->Parameters.Create.Options |= pCtx->ulOptions;
}

//simple completion routine sets the event that the mainline code waits on,
//and claims ownership of the irp by returning smpr.
NTSTATUS NrCreateComplete(PDEVICE_OBJECT pDev, PIRP pIrp, PKEVENT pEvent)
{
if (pEvent != NULL)
{
KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
}
return (STATUS_MORE_PROCESSING_REQUIRED);
}

NTSTATUS NrClose(PDEVICE_OBJECT pFilter, PIRP pIrp, PNRCREATE_CONTEXT pCtx)
{
IoCancelFileOpen(pFilter,
IoGetCurrentIrpStackLocation(pIrp)->FileObject);
NrRestoreIrp(pIrp, pCtx);

return STATUS_SUCCESS;
}

-----Original Message-----
From: Svante Moren [mailto:xxxxx@abaris.se]
Sent: Wednesday, February 21, 2001 3:42 PM
To: File Systems Developers
Subject: [ntfsd] Pre-query information for IRP_MJ_CREATE with
FILE_OPEN_BY_FILEID

Hi all!

In my filter driver I need to pre-query information for the file beeing
opened/created. I run into problems when I receive a IRP_MJ_CREATE with the
FILE_OPEN_BY_FILEID flag set. I would like to get the file name for that
file so that I then can open it and pre-query all required information as I
normally do. Letting the IRP complete is NOT an option, since the filter
driver needs to deny certain IRP_MJ_CREATEs.

TNX 1.0E6 in advance!

/Svante


You are currently subscribed to ntfsd as: xxxxx@ntpsoftware.com
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com