sys,dll: support file name normalization

This commit is contained in:
Bill Zissimopoulos
2016-10-17 14:23:56 -07:00
parent a653a010ce
commit 8d38a0dac6
8 changed files with 256 additions and 37 deletions

View File

@ -353,7 +353,7 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
UINT32 GrantedAccess;
PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
Result = FspFileSystemCreateCheck(FileSystem, Request, Response, TRUE,
&GrantedAccess, &ParentDescriptor);
@ -366,19 +366,29 @@ static NTSTATUS FspFileSystemOpCreate_FileCreate(FSP_FILE_SYSTEM *FileSystem,
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Create(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = FILE_CREATED;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}
@ -388,24 +398,34 @@ static NTSTATUS FspFileSystemOpCreate_FileOpen(FSP_FILE_SYSTEM *FileSystem,
NTSTATUS Result;
UINT32 GrantedAccess;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Open(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
if (!NT_SUCCESS(Result))
return Result;
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = FILE_OPENED;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}
@ -416,7 +436,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
UINT32 GrantedAccess;
PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
BOOLEAN Create = FALSE;
Result = FspFileSystemOpenCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
@ -430,10 +450,12 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
if (!Create)
{
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Open(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
@ -455,20 +477,30 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenIf(FSP_FILE_SYSTEM *FileSystem,
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Create(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
}
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OPENED;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}
@ -478,7 +510,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
NTSTATUS Result;
UINT32 GrantedAccess;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
BOOLEAN Supersede = FILE_SUPERSEDE == ((Request->Req.Create.CreateOptions >> 24) & 0xff);
Result = FspFileSystemOverwriteCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
@ -486,17 +518,27 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwrite(FSP_FILE_SYSTEM *FileSystem,
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Open(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
if (!NT_SUCCESS(Result))
return Result;
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}
@ -507,7 +549,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
UINT32 GrantedAccess;
PSECURITY_DESCRIPTOR ParentDescriptor, ObjectDescriptor;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
BOOLEAN Create = FALSE;
Result = FspFileSystemOverwriteCheck(FileSystem, Request, Response, TRUE, &GrantedAccess);
@ -521,10 +563,12 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
if (!Create)
{
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Open(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
if (!NT_SUCCESS(Result))
{
if (STATUS_OBJECT_NAME_NOT_FOUND != Result)
@ -546,20 +590,30 @@ static NTSTATUS FspFileSystemOpCreate_FileOverwriteIf(FSP_FILE_SYSTEM *FileSyste
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
Result = FileSystem->Interface->Create(FileSystem, Request,
(PWSTR)Request->Buffer, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
Request->Req.Create.FileAttributes, ObjectDescriptor, Request->Req.Create.AllocationSize,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
FspDeleteSecurityDescriptor(ObjectDescriptor, FspCreateSecurityDescriptor);
if (!NT_SUCCESS(Result))
return Result;
}
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = Create ? FILE_CREATED : FILE_OVERWRITTEN;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}
@ -571,7 +625,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
PWSTR Parent, Suffix;
UINT32 GrantedAccess;
PVOID FileNode;
FSP_FSCTL_FILE_INFO FileInfo;
FSP_FSCTL_OPEN_FILE_INFO OpenFileInfo;
UINT32 Information;
Result = FspFileSystemOpenTargetDirectoryCheck(FileSystem, Request, Response, &GrantedAccess);
@ -579,11 +633,13 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
return Result;
FileNode = 0;
memset(&FileInfo, 0, sizeof FileInfo);
memset(&OpenFileInfo, 0, sizeof OpenFileInfo);
OpenFileInfo.NormalizedName = (PVOID)Response->Buffer;
OpenFileInfo.NormalizedNameSize = FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX;
FspPathSuffix((PWSTR)Request->Buffer, &Parent, &Suffix, Root);
Result = FileSystem->Interface->Open(FileSystem, Request,
Parent, Request->Req.Create.CaseSensitive, Request->Req.Create.CreateOptions,
&FileNode, &FileInfo);
&FileNode, &OpenFileInfo.FileInfo);
FspPathCombine((PWSTR)Request->Buffer, Suffix);
if (!NT_SUCCESS(Result))
return Result;
@ -595,10 +651,18 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
Information = NT_SUCCESS(Result) ? FILE_EXISTS : FILE_DOES_NOT_EXIST;
}
if (FSP_FSCTL_TRANSACT_PATH_SIZEMAX >= OpenFileInfo.NormalizedNameSize)
{
Response->Size = (UINT16)(sizeof *Response + OpenFileInfo.NormalizedNameSize);
Response->Rsp.Create.Opened.FileName.Offset = 0;
Response->Rsp.Create.Opened.FileName.Size = (UINT16)OpenFileInfo.NormalizedNameSize;
}
Response->IoStatus.Information = Information;
USERCONTEXT(Response->Rsp.Create.Opened) = (UINT_PTR)FileNode;
Response->Rsp.Create.Opened.GrantedAccess = GrantedAccess;
memcpy(&Response->Rsp.Create.Opened.FileInfo, &FileInfo, sizeof FileInfo);
memcpy(&Response->Rsp.Create.Opened.FileInfo,
&OpenFileInfo.FileInfo, sizeof OpenFileInfo.FileInfo);
return STATUS_SUCCESS;
}

View File

@ -488,7 +488,7 @@ static NTSTATUS FspFsvolCreateNoLock(
RtlCopyMemory(Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
SecurityDescriptor, SecurityDescriptorSize);
/* fix FileNode->FileName if we were doing SL_OPEN_TARGET_DIRECTORY */
/* fix FileNode->FileName if we are doing SL_OPEN_TARGET_DIRECTORY */
if (Request->Req.Create.OpenTargetDirectory)
{
UNICODE_STRING Suffix;
@ -605,6 +605,7 @@ NTSTATUS FspFsvolCreateComplete(
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
FSP_FILE_NODE *OpenedFileNode;
UNICODE_STRING NormalizedName;
PREPARSE_DATA_BUFFER ReparseData;
UNICODE_STRING ReparseTargetPrefix0, ReparseTargetPrefix1, ReparseTargetPath;
@ -760,6 +761,35 @@ NTSTATUS FspFsvolCreateComplete(
}
/* populate the FileNode/FileDesc fields from the Response */
if (!FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch)
{
/* is there a normalized file name as part of the response? */
if (0 == Response->Rsp.Create.Opened.FileName.Size)
{
/* if not, the default is to upper case the name */
FspFileNameUpcase(&FileNode->FileName, &FileNode->FileName, 0);
}
else
{
/* if yes, verify it and then set it */
if (Response->Buffer + Response->Rsp.Create.Opened.FileName.Size >
(PUINT8)Response + Response->Size)
FSP_RETURN(Result = STATUS_OBJECT_NAME_INVALID);
NormalizedName.Length = NormalizedName.MaximumLength =
Response->Rsp.Create.Opened.FileName.Size;
NormalizedName.Buffer = (PVOID)Response->Buffer;
/* normalized file name can only differ in case from requested one */
if (0 != FspFileNameCompare(&FileNode->FileName, &NormalizedName, TRUE, 0))
FSP_RETURN(Result = STATUS_OBJECT_NAME_INVALID);
ASSERT(FileNode->FileName.Length == NormalizedName.Length);
RtlCopyMemory(FileNode->FileName.Buffer, NormalizedName.Buffer, NormalizedName.Length);
}
}
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,

View File

@ -699,6 +699,11 @@ static RTL_GENERIC_COMPARE_RESULTS NTAPI FspFsvolDeviceCompareContextByName(
PUNICODE_STRING SecondFileName = *(PUNICODE_STRING *)SecondElement;
LONG ComparisonResult;
/*
* Since FileNode FileName's are now always normalized, we could perhaps get away
* with using CaseInsensitive == FALSE at all times. For safety reasons we avoid
* doing so here.
*/
ComparisonResult = FspFileNameCompare(FirstFileName, SecondFileName, CaseInsensitive, 0);
if (0 > ComparisonResult)

View File

@ -437,6 +437,10 @@ BOOLEAN FspFileNameIsValid(PUNICODE_STRING Path, PUNICODE_STRING StreamPart, PUL
BOOLEAN FspFileNameIsValidPattern(PUNICODE_STRING Pattern);
VOID FspFileNameSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
#if 0
NTSTATUS FspFileNameUpcase(
PUNICODE_STRING DestinationName,
PUNICODE_STRING SourceName,
PCWCH UpcaseTable);
LONG FspFileNameCompare(
PUNICODE_STRING Name1,
PUNICODE_STRING Name2,
@ -448,6 +452,7 @@ BOOLEAN FspFileNameIsPrefix(
BOOLEAN IgnoreCase,
PCWCH UpcaseTable);
#else
#define FspFileNameUpcase(D,S,U) (ASSERT(0 == (U)), RtlUpcaseUnicodeString(D,S,FALSE))
#define FspFileNameCompare(N1,N2,I,U) (ASSERT(0 == (U)), RtlCompareUnicodeString(N1,N2,I))
#define FspFileNameIsPrefix(N1,N2,I,U) (ASSERT(0 == (U)), RtlPrefixUnicodeString(N1,N2,I))
#endif