Comments (1)
One reply on ntfsd ML points this out:
Is there any way around it? yes, but undocumented and only in case IO_REPARSE_TAG_MOUNT_POINT (but not in case IO_REPARSE_TAG_SYMLINK)
first of all - why this happens ? this is done by NTFS in NtfsFindStartingNode procedure
NTFS uppercase file name during parsing in NtfsFindStartingNode for calculate hash
which than used in NtfsFindPrefixHashEntry. also if PrefixHashEntry found - NTFS revert file name component back,
by call memmove from NtfsFindPrefixHashEntry. so NTFS usual temporary uppercase file name and than revert it to original form
but in case reparse point found - uppercase whole name, but revert back only until reparse name.
part after reparse file name left in uppercase
in case say \Pool\HelloWorld\XxXx NTFS first convert name to \POOL\HELLOWORLD\XXXX, then revert back to \Pool\HELLOWORLD\XXXX
and return STATUS_REPARSE with IO_REPARSE_TAG_MOUNT_POINT in your case and return
Tail.Overlay.AuxiliaryBuffer will point to REPARSE_DATA_BUFFER
assume that in REPARSE_DATA_BUFFER will be \Pool -> \MyDevice[\SomePath]
based on this info IopParseDevice transorm file name and new Irp will be sendto \MyDevice device
new file name will be [\SomePath]\HELLOWORLD\XXXX
before win7 (or vista - i not check here) when you view request to [\SomePath]\HELLOWORLD\XXXX
you can not even know - are user direct open
\MyDevice[\SomePath]\HELLOWORLD\XXXX
or open via reparse
\??\c:\Pool\HELLOWORLD\XXXX
but after extra create parameter (ECP) appeared, situation is changed.
begin how minimum win7 (i not check on vista) special IopSymlinkECPGuid exist in kernel:
struct __declspec(uuid("73d5118a-88ba-439f-92f4-46d38952d250")) IopSymlinkECPGuid;
and IopParseDevice attach ECP context of type IopSymlinkECPGuid to Irp after reparse.
so now we can know exactly, are create request was via reparse - need check for IopSymlinkECPGuid
PECP_LIST EcpList;
SYMLINK_ECP_CONTEXT* EcpContext;
if (0 <= FsRtlGetEcpListFromIrp(Irp, &EcpList) && EcpList &&
0 <= FsRtlFindExtraCreateParameter(EcpList, &__uuidof(IopSymlinkECPGuid), (void**)&EcpContext, 0)){
//...
}
the context point to next structure:
struct SYMLINK_ECP_CONTEXT
{
USHORT UnparsedNameLength;
union {
USHORT Flags;
struct {
USHORT MountPoint : 1;
};
};
USHORT DeviceNameLength;
USHORT Zero;
SYMLINK_ECP_CONTEXT* Reparsed;
UNICODE_STRING Name;
};
the Flags i not exactly research -
in case IO_REPARSE_TAG_MOUNT_POINT (a00000003) low bit is set to 1, Flags == 3
in case IO_REPARSE_TAG_SYMLINK (a000000c) Flags == 2
also exist special case for undocumented reparse tag 80000019
the Name always containing full path (including device name) to file
Zero always init to 0 (padding field)
DeviceNameLength containing length in bytes of device path in Name
in case IO_REPARSE_TAG_MOUNT_POINT:
Name containing original file path from open request
UnparsedNameLength containing length in bytes of unparsed suffix (path after mount pount component)
Reparsed point to linked SYMLINK_ECP_CONTEXT data with
Flags = 0, Name containing reparsed file path
in case IO_REPARSE_TAG_SYMLINK the UnparsedNameLength and Reparsed is always 0
and Name containing reparsed file path
so in case IO_REPARSE_TAG_SYMLINK SYMLINK_ECP_CONTEXT containing much less info compare IO_REPARSE_TAG_MOUNT_POINT.
let concrete example:
on \Device\HarddiskVolume2 exist mount point :
\Pool -> \MyDevice[\SomePath]
and somebody try open file \Device\HarddiskVolume2\Pool\HelloWorld\XxXx
----- Irp #1 to \Device\HarddiskVolume2 --------
FileName = \Pool\HelloWorld\XxXx
no IopSymlinkECPGuid context
NTFS transform FileName to \Pool\HELLOWORLD\XXXX and return
(STATUS_REPARSE, IO_REPARSE_TAG_MOUNT_POINT)
----- Irp #2 to \MyDevice --------
FileName = [\SomePath]\HELLOWORLD\XXXX
exist IopSymlinkECPGuid context (Flags = 3):
Name = \Device\HarddiskVolume2\Pool\HelloWorld\XxXx
DeviceNameLength = size of L"\Device\HarddiskVolume2" (not including terminated 0)
UnparsedNameLength = sizeof of L"\HelloWorld\XxXx" (not including terminated 0)
Reparsed -> IopSymlinkECPGuid context (Flags = 0):
Name = \MyDevice[\SomePath]\HELLOWORLD\XXXX
DeviceNameLength = size of L"\MyDevice"
UnparsedNameLength = 0
Reparsed = 0
so based on this info you can got original unparsed file name (in original case) - \HelloWorld\XxXx
and modify file name from [\SomePath]\HELLOWORLD\XXXX to \HelloWorld\XxXx
BOOLEAN RevertFileName(PIRP Irp)
{
PECP_LIST EcpList;
SYMLINK_ECP_CONTEXT* EcpContext;
if (0 <= FsRtlGetEcpListFromIrp(Irp, &EcpList) &&
EcpList &&
0 <= FsRtlFindExtraCreateParameter(EcpList, &__uuidof(IopSymlinkECPGuid), (void**)&EcpContext, 0) &&
!FsRtlIsEcpFromUserMode(EcpContext) &&
EcpContext->MountPoint
)
{
if (USHORT UnparsedNameLength = EcpContext->UnparsedNameLength)
{
PUNICODE_STRING FileName = &IoGetCurrentIrpStackLocation(Irp)->FileObject->FileName;
USHORT FileNameLength = FileName->Length;
USHORT NameLength = EcpContext->Name.Length;
if (UnparsedNameLength <= NameLength && UnparsedNameLength <= FileNameLength)
{
UNICODE_STRING us1 = {
UnparsedNameLength,
UnparsedNameLength,
(PWSTR)RtlOffsetToPointer(FileName->Buffer, FileNameLength - UnparsedNameLength)
};
UNICODE_STRING us2 = {
UnparsedNameLength,
UnparsedNameLength,
(PWSTR)RtlOffsetToPointer(EcpContext->Name.Buffer, NameLength - UnparsedNameLength)
};
if (RtlEqualUnicodeString(&us1, &us2, TRUE))
{
memcpy(us1.Buffer, us2.Buffer, UnparsedNameLength);
return TRUE;
}
}
}
}
return FALSE;
}
some logs:
https://i.imgur.com/fUUFRWM.png https://pastebin.com/nRpZrZtJ
https://i.imgur.com/W3ywGUw.png https://pastebin.com/kCvzMRyi
https://i.imgur.com/2k0dARs.png https://pastebin.com/geHM893X
from zfsin.
Related Issues (20)
- Unable to import or detect a pool HOT 33
- System hangs on "zpool import" HOT 1
- Stuck when export a pool create by O3X HOT 1
- [BSOD]critical process died on zpool import win10 2004 HOT 2
- zstd / openzfs 2.0.3? HOT 7
- Exporting a USB-based pool, can't import because UNAVAIL HOT 1
- zpool export does not work HOT 2
- xattr=sa support? HOT 2
- Wrong modification times? HOT 2
- TargetId and Lun is created for zvol before it is fully open HOT 1
- Is FC HBA WMI functionality required? HOT 1
- ZFS on windows HOT 2
- alive ? HOT 9
- QuickPrint dekstop application on mac HOT 4
- bug check HOT 4
- ZDB failing on debug 2.1.6 HOT 1
- Creating zpool on separate partition on same vdev works but flags an error HOT 5
- Archive this repository HOT 2
- Zpool import takes ~10 mins. HOT 11
- Crashes my device HOT 13
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from zfsin.