diff --git a/src/sys/create.c b/src/sys/create.c index 6845709d..1dd18808 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -134,6 +134,7 @@ static NTSTATUS FspFsvolCreateNoLock( PFILE_OBJECT FileObject = IrpSp->FileObject; PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject; UNICODE_STRING FileName = FileObject->FileName; + UNICODE_STRING MainStreamName = { 0 }, StreamPart = { 0 }; /* open the volume object? */ if ((0 == RelatedFileObject || !FspFileNodeIsValid(RelatedFileObject->FsContext)) && @@ -211,9 +212,27 @@ static NTSTATUS FspFsvolCreateNoLock( } /* check filename validity */ - if (!FspUnicodePathIsValid(&FileName, 0 != FsvolDeviceExtension->VolumeParams.NamedStreams)) + if (!FspUnicodePathIsValid(&FileName, + FsvolDeviceExtension->VolumeParams.NamedStreams ? &StreamPart : 0)) return STATUS_OBJECT_NAME_INVALID; + /* if we have a stream part */ + if (0 != StreamPart.Buffer) + { + ASSERT( + FileName.Buffer <= StreamPart.Buffer && + StreamPart.Buffer + StreamPart.Length / sizeof(WCHAR) <= + FileName.Buffer + FileName.Length / sizeof(WCHAR)); + + FileName.Length = (USHORT) + (((PUINT8)StreamPart.Buffer + StreamPart.Length / sizeof(WCHAR)) - + (PUINT8)FileName.Buffer - 1); + + MainStreamName.Length = MainStreamName.MaximumLength = (USHORT) + ((PUINT8)StreamPart.Buffer - (PUINT8)FileName.Buffer - 1); + MainStreamName.Buffer = FileName.Buffer; + } + /* is this a relative or absolute open? */ if (0 != RelatedFileObject) { diff --git a/src/sys/driver.h b/src/sys/driver.h index dc81e8de..05b21ce1 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -425,7 +425,7 @@ BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime) /* utility */ PVOID FspAllocatePoolMustSucceed(POOL_TYPE PoolType, SIZE_T Size, ULONG Tag); PVOID FspAllocateIrpMustSucceed(CCHAR StackSize); -BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart); BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern); VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); NTSTATUS FspCreateGuid(GUID *Guid); diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index d8f9af55..082dba14 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -1085,7 +1085,7 @@ static NTSTATUS FspFsvolSetRenameInformation( if (FileNode->IsRootDirectory) /* cannot rename root directory */ return STATUS_INVALID_PARAMETER; - if (!FspUnicodePathIsValid(&FileNode->FileName, FALSE)) + if (!FspUnicodePathIsValid(&FileNode->FileName, 0)) /* cannot rename streams (WinFsp limitation) */ return STATUS_INVALID_PARAMETER; @@ -1110,7 +1110,7 @@ static NTSTATUS FspFsvolSetRenameInformation( if (L'\\' == Suffix.Buffer[0]) FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix); - if (!FspUnicodePathIsValid(&Remain, FALSE) || !FspUnicodePathIsValid(&Suffix, FALSE)) + if (!FspUnicodePathIsValid(&Remain, 0) || !FspUnicodePathIsValid(&Suffix, 0)) { /* cannot rename streams (WinFsp limitation) */ Result = STATUS_INVALID_PARAMETER; diff --git a/src/sys/util.c b/src/sys/util.c index d01031ec..6cffe1d0 100644 --- a/src/sys/util.c +++ b/src/sys/util.c @@ -17,7 +17,7 @@ #include -BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams); +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart); BOOLEAN FspUnicodePathIsValidPattern(PUNICODE_STRING Pattern); VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); NTSTATUS FspCreateGuid(GUID *Guid); @@ -171,7 +171,7 @@ PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) } } -BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) +BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart) { PAGED_CODE(); @@ -180,6 +180,7 @@ BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) PWSTR PathBgn, PathEnd, PathPtr; UCHAR Flags = FSRTL_NTFS_LEGAL; + ULONG Colons = 0; WCHAR Char; PathBgn = Path->Buffer; @@ -193,7 +194,7 @@ BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) if (L'\\' == Char) { /* stream names can only appear as the last path component */ - if (BooleanFlagOn(Flags, FSRTL_OLE_LEGAL)) + if (0 < Colons) return FALSE; PathPtr++; @@ -204,17 +205,32 @@ BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams) } else if (L':' == Char) { - if (!AllowStreams) + if (0 == StreamPart) return FALSE; /* * Where are the docs on legal stream names? */ - PathPtr++; - /* stream characters now allowed */ - SetFlag(Flags, FSRTL_OLE_LEGAL); + Flags = FSRTL_NTFS_STREAM_LEGAL; + + PathPtr++; + Colons++; + + if (1 == Colons) + { + /* first time through: set up StreamPart */ + StreamPart->Length = StreamPart->MaximumLength = + (USHORT)((PUINT8)PathEnd - (PUINT8)PathPtr); + StreamPart->Buffer = PathPtr; + } + else if (2 == Colons) + { + /* second time through: fix StreamPart length to not include 2nd colon */ + StreamPart->Length = + (USHORT)((PUINT8)PathPtr - (PUINT8)StreamPart->Buffer - 1); + } } else if (0x80 > Char && !FsRtlTestAnsiCharacter(Char, TRUE, FALSE, Flags)) return FALSE;