Robin,
I agree with your analysis - it is FAT (or NTFS) that is initializing the
Vpb, not the I/O manager. Since LanManager would not do this (it does not
use Vpb pointers), that would explain why it works as you expected for
LanManager.
Now, I suppose the point here is that the initial issue you raised is that
the filters who observe the IRP_MJ_CLEANUP and IRP_MJ_CLOSE operation might
find this “confusing”. However, I will note:
* IoCreateStreamFileObject and IoCreateStreamFileObjectLite both create file
objects for which the filter driver does not see an IRP_MJ_CLEANUP or
IRP_MJ_CLOSE.
* IoCreateFileSpecifyDeviceObjectHint (the anti-reentrancy change in Windows
XP) has exactly the same behavior/semantics as the shadow device object
technique.
If these are not sufficient grounds, then the obviously question would be
“what are you willing to do to resolve this particular problem”. I can see
a couple of possible options - but they are JUST options and I’ve never
tried them before:
* Create stream file objects in your filter driver. Then you can use the
stream file objects when calling FAT/NTFS. The I/O Manager will know
nothing of those stream file objects and will call your FSD directly. This
is quite a bit more work for you, though.
* Change the Vpb pointer in the file object before you close the handle. As
a general rule, you should not do this. However, since you own this file
object and nobody else will be using it, you can set this to zero. Then
close the handle. The I/O Manager will pass it to your filter. You restore
the Vpb pointer and pass it to FAT/NTFS (or the filter below you). This is
NOT a general solution, since you cannot do this if anyone else is using the
file object (there are code paths in the FAT code that rely upon the
FileObject->Vpb). I’m not fond of this solution, since I don’t like
“substituting” fields in OS data structures (at least this one belongs to
the FSD…)
There are no doubt other ideas, but this should give you something to at
least consider.
Regards,
Tony
Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com
-----Original Message-----
From: Robin [mailto:xxxxx@xpsonline.com]
Sent: Sunday, March 17, 2002 6:46 AM
To: File Systems Developers
Subject: [ntfsd] RE: Opening file through “ShadowDeviceObject”
At 11:40 PM 3/16/02, Tony Mason wrote:
Robin,
Your description of what you are observing still makes me believe that
there
is an error in implementation here.
The FileObject that is sent to your “shadow device object” would not have a
Vpb, because your shadow device is not associated with a physical volume.
That’s right.
Your description of what you observe would suggest that you are not opening
the file against your shadow file object.
No, that is not the case as I stated earlier. Here is how I am doing it.
Say, to open a file named “\Windows\SomeFileName.txt”, I am prepending the
shadow device object name like
“\Device\ShadowVolumeXX\Windows\SomeFileName.txt” (where XX is some unique
number). In case of network re-director this will be something like
“\Device\ShadowVolumeXX\CompName\ShareName\SomeFileName.txt”. Then I am
passing this file name to ZwCreateFile as shown below.
IO_STATUS_BLOCK ioStatus;
OBJECT_ATTRIBUTES objAttr;
NTSTATUS ntStatus;
InitializeObjectAttributes( &objAttr, FileName, OBJ_CASE_INSENSITIVE, NULL,
NULL);
ntStatus = ZwCreateFile( &hFile, Access, &objAttr, &ioStatus, . . .);
if (NT_SUCCESS( ntStatus))
{
ntStatus = ObReferenceObjectByHandle( hFile, Access, *IoFileObjectType,
KernelMode, (PVOID*)&fileObj,
NULL);
}
return ntStatus;
When the above function returns I see that fileObj->Vpb is set for the
Fastfat and Ntfs volumes. For Lanman redirector it is always set to NULL as
expected.
When closing the file, I am using the following code.
ObDereferenceObject( fileObj);
status = ZwClose( hFile);
You can see there is not much scope to make errors here, and I/O Manager is
correctly sending the create IRP to my shadow device object (no reentrancy
here). In shadow device object handler I am just skipping the stack
location and passing the Irp down to the next filter device object (I have
a separate filter device object attached to that device object). The shadow
device object is a simple device object (NOT attached to anything)
containing a pointer to our filter device object, which in turn contains a
pointer to next filter device object on the stack.
To use the “shadow device object” approach for re-opening a file, you
specify the name of your shadow device object along with the balance of the
name to be parsed by the underlying driver in a call to ZwCreateFile or
IoCreateFile. When the I/O Manager is called (IopParseDevice) it will get
a
copy of your shadow device object and the balance of your name. Since
another filter (like FileMon) would not layer on top of your shadow device
object, you wouldn’t have the issues of re-entrancy.
I understand this.
There is no way, in this scheme, for the I/O Manager to associate the file
object with a Vpb - your shadow device object does not have one, so the
file
object should not have one (much in the same way it associates the network
file system’s device object, even though it does not have a Vpb).
So, my question to you is how does the I/O Manager associate the Vpb for a
different device with the file object created against your shadow device?
The I/O Manager is NOT associating the Vpb with the FileObject as you
explained above. In fact when the create Irp comes (as a result of calling
ZwCreateFile above) to our shadow device object handler, FileObject->Vpb is
always set to NULL for both the local as well as network FSDs. To see who
is setting the Vpb pointer, I set a memory write break-point on
FileObject->Vpb and found that following codes in Fastfat and Ntfs are
setting this value.
NtfsSetFileObject+0019
FatSetFileObject+001D
This in on Windows XP Pro retail version (you might have access to the
source code to verify it).
I don’t know why both Fastfat and Ntfs is setting the Vpb pointer in
FileObject, but there must be some good reason to do that.
Regards,
Robin
You are currently subscribed to ntfsd as: xxxxx@osr.com
To unsubscribe send a blank email to %%email.unsub%%