'reusing' a create irp... a few questions

Hello,
Remember that endless thread about reentering the top of the file
system device stack within a create dispatch routine (by ZwCreate-ing the
target of the original open) and all of the problem it can cause? Well, as
suggested, I’ve taken out that recursion and instead now ‘reuse’ the create
irp:
I have to know the file’s size before the create hits the FSD,
because an overwrite or supersede will truncate the file (and it is
important for my file to account for size changing io). So, what I now do
is check the disposition of the create irp. If it is a destructive create I
neuter it by setting the disposition to FILE_OPEN. I then register a
completion routine (which simply sets an event and returns
STATUS_MORE_PROCESSING_REQUIRED) and send the irp down with IoCallDriver.
After the FSD completes the irp, if the file was successfully opened (if it
existed) I can get its size. Next I force the file closed again using
IoCancelFileOpen. Then I restore the original disposition and AND out the
FO_CLEANUP_COMPLETE flag.
At this point, I leave the special case code to handle destructive
creates with an irp that is as good as new (I think). I then just send the
irp down normally.
Thanks for the suggestion, this method seems to work well and is
non-recursive. I wouldn’t have had the audacity to think I could re-use an
irp like this unless someone told me I could.
Anyway, does my implementation sound ok? Any pitfalls that are
obvious to you more experienced folk? Also, since IoCancelFileOpen does not
exist in NT4, could someone tell me how I can cleanly and safely close the
file from my dispatch routine in NT4? (BTW will ObDereferenceFileObject
generate cleanups or closes as appropriate directed to the fileobject being
dereferenced if the reference counts go to zero?).

Thanks,
Joel

hold it there is a problem: it seems that under NTFS, calling
IoCancelFileOpen causes the FILE_OBJECT.FileName.Length to be set to 1(??).
The buffer and maximum length are still intact. This seems easy to work
around, but it makes me nervous. Can anyone explain this?

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 8:56 AM
To: ‘xxxxx@lists.osr.com’
Subject: ‘reusing’ a create irp… a few questions

Hello,
Remember that endless thread about reentering the top of the file
system device stack within a create dispatch routine (by ZwCreate-ing the
target of the original open) and all of the problem it can cause? Well,
as suggested, I’ve taken out that recursion and instead now ‘reuse’ the
create irp:
I have to know the file’s size before the create hits the FSD,
because an overwrite or supersede will truncate the file (and it is
important for my file to account for size changing io). So, what I now do
is check the disposition of the create irp. If it is a destructive create
I neuter it by setting the disposition to FILE_OPEN. I then register a
completion routine (which simply sets an event and returns
STATUS_MORE_PROCESSING_REQUIRED) and send the irp down with IoCallDriver.
After the FSD completes the irp, if the file was successfully opened (if
it existed) I can get its size. Next I force the file closed again using
IoCancelFileOpen. Then I restore the original disposition and AND out the
FO_CLEANUP_COMPLETE flag.
At this point, I leave the special case code to handle destructive
creates with an irp that is as good as new (I think). I then just send
the irp down normally.
Thanks for the suggestion, this method seems to work well and is
non-recursive. I wouldn’t have had the audacity to think I could re-use
an irp like this unless someone told me I could.
Anyway, does my implementation sound ok? Any pitfalls that are
obvious to you more experienced folk? Also, since IoCancelFileOpen does
not exist in NT4, could someone tell me how I can cleanly and safely close
the file from my dispatch routine in NT4? (BTW will
ObDereferenceFileObject generate cleanups or closes as appropriate
directed to the fileobject being dereferenced if the reference counts go
to zero?).

Thanks,
Joel

alright nevermind that… I needed an NT4 build, so I commented out the
IoCancelFileOpen call and built. To my surprise, it still works. Do I need
this call? Right now, my code looks like this:

if (destructive disposition)
{
createdisposition = benign_disposition
IoCallDriver(pDev, pIrp)
createdisposition = original_disposition

/* used to call IoCancelFileOpen here */
}
IoCallDriver(pDev, pIrp)

It seems to me that I should have to do some sort of cleanup on the file
object after the first IoCallDriver - do I? I tried dereferencing the file
object, but that caused a bugcheck.

THanks,
Joel

-----Original Message-----
From: Smith, Joel [mailto:xxxxx@ntpsoftware.com]
Sent: Wednesday, July 26, 2000 9:34 AM
To: File Systems Developers
Subject: [ntfsd] RE: ‘reusing’ a create irp… a few questions

hold it there is a problem: it seems that under NTFS, calling
IoCancelFileOpen causes the FILE_OBJECT.FileName.Length to be set to 1(??).
The buffer and maximum length are still intact. This seems easy to work
around, but it makes me nervous. Can anyone explain this?

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 8:56 AM
To: ‘xxxxx@lists.osr.com’
Subject: ‘reusing’ a create irp… a few questions

Hello,
Remember that endless thread about reentering the top of the file
system device stack within a create dispatch routine (by ZwCreate-ing the
target of the original open) and all of the problem it can cause? Well, as
suggested, I’ve taken out that recursion and instead now ‘reuse’ the create
irp:

I have to know the file’s size before the create hits the
FSD, because an overwrite or supersede will truncate the file (and it is
important for my file to account for size changing io). So, what I now do
is check the disposition of the create irp. If it is a destructive create I
neuter it by setting the disposition to FILE_OPEN. I then register a
completion routine (which simply sets an event and returns
STATUS_MORE_PROCESSING_REQUIRED) and send the irp down with IoCallDriver.
After the FSD completes the irp, if the file was successfully opened (if it
existed) I can get its size. Next I force the file closed again using
IoCancelFileOpen. Then I restore the original disposition and AND out the
FO_CLEANUP_COMPLETE flag.

At this point, I leave the special case code to handle
destructive creates with an irp that is as good as new (I think). I then
just send the irp down normally.

Thanks for the suggestion, this method seems to work well
and is non-recursive. I wouldn’t have had the audacity to think I could
re-use an irp like this unless someone told me I could.

Anyway, does my implementation sound ok? Any pitfalls that
are obvious to you more experienced folk? Also, since IoCancelFileOpen does
not exist in NT4, could someone tell me how I can cleanly and safely close
the file from my dispatch routine in NT4? (BTW will ObDereferenceFileObject
generate cleanups or closes as appropriate directed to the fileobject being
dereferenced if the reference counts go to zero?).

Thanks,
Joel

Of course this isn’t going to work… Its going to artificially bump up
any FSD refcounts on its FCB’s, right? Correct me if I’m wrong but I better
send a cleanup and close to the FSD.

Thanks,
Joel

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 12:07 PM
To: ‘File Systems Developers’
Subject: RE: [ntfsd] RE: ‘reusing’ a create irp… a few questions

alright nevermind that… I needed an NT4 build, so I commented out the
IoCancelFileOpen call and built. To my surprise, it still works. Do I need
this call? Right now, my code looks like this:

if (destructive disposition)
{
createdisposition = benign_disposition
IoCallDriver(pDev, pIrp)
createdisposition = original_disposition

/* used to call IoCancelFileOpen here */
}
IoCallDriver(pDev, pIrp)

It seems to me that I should have to do some sort of cleanup on the file
object after the first IoCallDriver - do I? I tried dereferencing the file
object, but that caused a bugcheck.

THanks,
Joel

-----Original Message-----
From: Smith, Joel [mailto:xxxxx@ntpsoftware.com]
Sent: Wednesday, July 26, 2000 9:34 AM
To: File Systems Developers
Subject: [ntfsd] RE: ‘reusing’ a create irp… a few questions

hold it there is a problem: it seems that under NTFS, calling
IoCancelFileOpen causes the FILE_OBJECT.FileName.Length to be set to 1(??).
The buffer and maximum length are still intact. This seems easy to work
around, but it makes me nervous. Can anyone explain this?

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 8:56 AM
To: ‘xxxxx@lists.osr.com’
Subject: ‘reusing’ a create irp… a few questions

Hello,
Remember that endless thread about reentering the top of the file
system device stack within a create dispatch routine (by ZwCreate-ing the
target of the original open) and all of the problem it can cause? Well, as
suggested, I’ve taken out that recursion and instead now ‘reuse’ the create
irp:

I have to know the file’s size before the create hits the
FSD, because an overwrite or supersede will truncate the file (and it is
important for my file to account for size changing io). So, what I now do
is check the disposition of the create irp. If it is a destructive create I
neuter it by setting the disposition to FILE_OPEN. I then register a
completion routine (which simply sets an event and returns
STATUS_MORE_PROCESSING_REQUIRED) and send the irp down with IoCallDriver.
After the FSD completes the irp, if the file was successfully opened (if it
existed) I can get its size. Next I force the file closed again using
IoCancelFileOpen. Then I restore the original disposition and AND out the
FO_CLEANUP_COMPLETE flag.

At this point, I leave the special case code to handle
destructive creates with an irp that is as good as new (I think). I then
just send the irp down normally.

Thanks for the suggestion, this method seems to work well
and is non-recursive. I wouldn’t have had the audacity to think I could
re-use an irp like this unless someone told me I could.

Anyway, does my implementation sound ok? Any pitfalls that
are obvious to you more experienced folk? Also, since IoCancelFileOpen does
not exist in NT4, could someone tell me how I can cleanly and safely close
the file from my dispatch routine in NT4? (BTW will ObDereferenceFileObject
generate cleanups or closes as appropriate directed to the fileobject being
dereferenced if the reference counts go to zero?).

Thanks,
Joel

Sending a cleanup and close to the FSD seems to work. An interesting
note though, the side effect of calling IoCancelFileOpen I described below
(where the filename.length was set to 1) is actually a side effect of
sending an IRP_MJ_CLOSE to the FSD. Currently, I simply restore the length
value after closing the file object in my dispatch routine, which seems to
work ok.
Thanks,
Joel
(I’ll stop talking to myself now)

-----Original Message-----
From: Smith, Joel
Sent: Thursday, July 27, 2000 8:34 AM
To: ‘xxxxx@lists.osr.com’
Subject: RE: [ntfsd] RE: ‘reusing’ a create irp… a few questions

Of course this isn’t going to work… Its going to artificially bump up
any FSD refcounts on its FCB’s, right? Correct me if I’m wrong but I better
send a cleanup and close to the FSD.

Thanks,
Joel

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 12:07 PM
To: ‘File Systems Developers’
Subject: RE: [ntfsd] RE: ‘reusing’ a create irp… a few questions

alright nevermind that… I needed an NT4 build, so I commented out the
IoCancelFileOpen call and built. To my surprise, it still works. Do I need
this call? Right now, my code looks like this:

if (destructive disposition)
{
createdisposition = benign_disposition
IoCallDriver(pDev, pIrp)
createdisposition = original_disposition

/* used to call IoCancelFileOpen here */
}
IoCallDriver(pDev, pIrp)

It seems to me that I should have to do some sort of cleanup on the file
object after the first IoCallDriver - do I? I tried dereferencing the file
object, but that caused a bugcheck.

THanks,
Joel

-----Original Message-----
From: Smith, Joel [mailto:xxxxx@ntpsoftware.com]
Sent: Wednesday, July 26, 2000 9:34 AM
To: File Systems Developers
Subject: [ntfsd] RE: ‘reusing’ a create irp… a few questions

hold it there is a problem: it seems that under NTFS, calling
IoCancelFileOpen causes the FILE_OBJECT.FileName.Length to be set to 1(??).
The buffer and maximum length are still intact. This seems easy to work
around, but it makes me nervous. Can anyone explain this?

-----Original Message-----
From: Smith, Joel
Sent: Wednesday, July 26, 2000 8:56 AM
To: ‘xxxxx@lists.osr.com’
Subject: ‘reusing’ a create irp… a few questions

Hello,
Remember that endless thread about reentering the top of the file
system device stack within a create dispatch routine (by ZwCreate-ing the
target of the original open) and all of the problem it can cause? Well, as
suggested, I’ve taken out that recursion and instead now ‘reuse’ the create
irp:

I have to know the file’s size before the create hits the
FSD, because an overwrite or supersede will truncate the file (and it is
important for my file to account for size changing io). So, what I now do
is check the disposition of the create irp. If it is a destructive create I
neuter it by setting the disposition to FILE_OPEN. I then register a
completion routine (which simply sets an event and returns
STATUS_MORE_PROCESSING_REQUIRED) and send the irp down with IoCallDriver.
After the FSD completes the irp, if the file was successfully opened (if it
existed) I can get its size. Next I force the file closed again using
IoCancelFileOpen. Then I restore the original disposition and AND out the
FO_CLEANUP_COMPLETE flag.

At this point, I leave the special case code to handle
destructive creates with an irp that is as good as new (I think). I then
just send the irp down normally.

Thanks for the suggestion, this method seems to work well
and is non-recursive. I wouldn’t have had the audacity to think I could
re-use an irp like this unless someone told me I could.

Anyway, does my implementation sound ok? Any pitfalls that
are obvious to you more experienced folk? Also, since IoCancelFileOpen does
not exist in NT4, could someone tell me how I can cleanly and safely close
the file from my dispatch routine in NT4? (BTW will ObDereferenceFileObject
generate cleanups or closes as appropriate directed to the fileobject being
dereferenced if the reference counts go to zero?).

Thanks,
Joel

‘reusing’ a create irp… a few questions>to you more experienced folk?
Also, since IoCancelFileOpen does not exist

in NT4, could someone tell me how I can cleanly and safely close the file
from
my dispatch routine in NT4?

Assemble CLEANUP and CLOSE IRPs by hand and send them down.
IIRC this is enough. Look in IoCancelFileOpen assembly in the w2k kernel.

(BTW will ObDereferenceFileObject generate cleanups or closes as
appropriate directed to the fileobject being dereferenced if the reference
counts go to zero?).

Wrong way.
To cancel the open in the filter is the open was already processed by the
lower FSD, you must:

  • send CLEANUP and CLOSE to the lower FSD in your completion routine
    (possibly by IoCancelFileOpen)
  • fail the CREATE IRP with some status by setting Irp->IoStatus.Status to
    some error and then returning STATUS_SUCCESS from the completion routine.

IopParseDevice will receive the error from CREATE IRP and will destroy the
file object itself. It is not your responsibility to destroy the file
object.

Max