Thanks for the debugger output, that certainly clears things up.
This is really cute and I must now admit that I clearly never fully thought
through this particular case. You are absolutely correct, the device
interface takes a different path than the symbolic link name. The reason why
is in the output you provided…
In the symbolic link case, the file object is an open instance of a Disk
device object:
kd> !fileobj 85043400
Device Object: 0x849e97b8 \Driver\Disk
Vpb: 0x849e9730
This is due to the fact that Disk calls IoCreateSymbolicLink and points this
link to its own FDO. Note the presence of the VPB, hence the I/O requests
are going to traverse to the file system stack.
However, in the case of the device interface the symbolic link that you
ultimately open points to the disk’s PDO (created by ATAPI):
kd> !fileobj 85040b48
Device Object: 0x848cc908 \Driver\atapi
This must not have been created with a device type of FILE_DEVICE_DISK
because it doesn’t have a VPB. If there’s no VPB, the I/O request goes to
the top of the device stack (which would be to PartMgr in this case).
(As an aside: you don’t get this problem in the volume stack because the
symbolic link name (HarddiskVolumeX) and the device interface both point to
the PDO created by volmgr, which has a VPB.)
So, you get two I/O paths to the disk from user mode. This makes for some
fun trivia points such as one path (PhysicalDriveX) implements share access
and the other (device interface) does not. Therefore you can open
PhysicalDriveX exclusively, but that doesn’t do you any good if someone else
opens via device interface.
Neat stuff and it highlights the problems with having multiple names in the
device stack. Bottom line: get yourself a disk filter if you really care
about this.
-scott
OSR
@OSRDrivers
wrote in message news:xxxxx@ntdev…
Handle for:
h = CreateFileA(“\\.\PhysicalDrive0”, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
0, 0);
looks like this:
kd> !handle a4 f
PROCESS 83cf3440 SessionId: 1 Cid: 0fb4 Peb: 7ffd9000 ParentCid: 0298
DirBase: 1ea284e0 ObjectTable: 83e18bc8 HandleCount: 41.
Image: ScratchPad.exe
Handle table at 83e18bc8 with 41 entries in use
00a4: Object: 85043400 GrantedAccess: 0012019f Entry: 83e49148
Object: 85043400 Type: (83a2ab90) File
ObjectHeader: 850433e8 (new version)
HandleCount: 1 PointerCount: 1
kd> !fileobj 85043400
Device Object: 0x849e97b8 \Driver\Disk
Vpb: 0x849e9730
Event signalled
Access: Read Write SharedRead SharedWrite SharedDelete
Flags: 0x44000a
Synchronous IO
No Intermediate Buffering
Handle Created
Volume Open
FsContext: 0x83acf930 FsContext2: 0x00000000
CurrentByteOffset: 0
kd> !devstack 0x849e97b8
!DevObj !DrvObj !DevExt ObjectName
849e93f8 \Driver\partmgr 849e94b0
849e97b8 \Driver\Disk 849e9870 DR0
849e9ef0 \Driver\storflt 849e8aa0
848cf020 \Driver\ACPI 83a4a770
848cc908 \Driver\atapi 848cc9c0 IdeDeviceP0T0L0-0
!DevNode 848d7950 :
DeviceInst is
“IDE\DiskVirtual_HD______________________________1.1.0___\5&35dc7040&0&0.0.0”
ServiceName is “disk”
When nt!ntWriteFile calls IoGetRelatedDeviceObject the function switches to
another stack resulting in:
kd> !devstack @eax
!DevObj !DrvObj !DevExt ObjectName
8508a980 \FileSystem\FltMgr 8508aa38
83acf878 \FileSystem\RAW 83acf930
It looks different when a disk is opened by interface symlink:
h = CreateFileW(pDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, 0);
//I tried with and without FILE_FLAG_NO_BUFFERING
kd> !handle dc
PROCESS 83cf3440 SessionId: 1 Cid: 0fb4 Peb: 7ffd9000 ParentCid: 0298
DirBase: 1ea284e0 ObjectTable: 83e18bc8 HandleCount: 55.
Image: ScratchPad.exe
Handle table at 83e18bc8 with 55 entries in use
00dc: Object: 85040b48 GrantedAccess: 0012019f Entry: 83e491b8
Object: 85040b48 Type: (83a2ab90) File
ObjectHeader: 85040b30 (new version)
HandleCount: 1 PointerCount: 1
kd> !fileobj 85040b48
Device Object: 0x848cc908 \Driver\atapi
Vpb is NULL
Event signalled
Flags: 0x4000a
Synchronous IO
No Intermediate Buffering
Handle Created
CurrentByteOffset: 0
kd> !devstack 0x848cc908
!DevObj !DrvObj !DevExt ObjectName
849e93f8 \Driver\partmgr 849e94b0
849e97b8 \Driver\Disk 849e9870 DR0
849e9ef0 \Driver\storflt 849e8aa0
848cf020 \Driver\ACPI 83a4a770
848cc908 \Driver\atapi 848cc9c0 IdeDeviceP0T0L0-0
!DevNode 848d7950 :
DeviceInst is
“IDE\DiskVirtual_HD______________________________1.1.0___\5&35dc7040&0&0.0.0”
ServiceName is “disk”
So VPB is NULL and IoGetRelatedDeviceObject doesnt switch stacks:
kd> !devstack @eax
!DevObj !DrvObj !DevExt ObjectName
849e93f8 \Driver\partmgr 849e94b0
849e97b8 \Driver\Disk 849e9870 DR0
849e9ef0 \Driver\storflt 849e8aa0
848cf020 \Driver\ACPI 83a4a770
848cc908 \Driver\atapi 848cc9c0 IdeDeviceP0T0L0-0
!DevNode 848d7950 :
DeviceInst is
“IDE\DiskVirtual_HD______________________________1.1.0___\5&35dc7040&0&0.0.0”
ServiceName is “disk”
Does it mean that a user mode application might open a disk bypassing
FltMgr? Why opening by interface differs from open by legacy symlink?