[NTFS] - Fix POSIX rules. Fix accessing long filenames created in Windows when 8dot3 name creation is disabled.

Whether or not a filename should be interpreted as case-sensitive is dependent on a flag passed to the driver when a file is created (opened); it's separate from the namespace associated with the file being accessed.

svn path=/branches/GSoC_2016/NTFS/; revision=75178
This commit is contained in:
Trevor Thompson 2017-06-24 04:36:28 +00:00 committed by Thomas Faber
parent 98ddf610bc
commit 032be02954
8 changed files with 185 additions and 44 deletions

View file

@ -115,6 +115,10 @@ AddData(PFILE_RECORD_HEADER FileRecord,
* @param ParentMftIndex * @param ParentMftIndex
* Pointer to a ULONGLONG which will receive the index of the parent directory. * Pointer to a ULONGLONG which will receive the index of the parent directory.
* *
* @param CaseSensitive
* Boolean indicating if the function should operate in case-sensitive mode. This will be TRUE
* if an application opened the file with the FILE_FLAG_POSIX_SEMANTICS flag.
*
* @return * @return
* STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end * STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end
* of the given file record. * of the given file record.
@ -132,7 +136,8 @@ AddFileName(PFILE_RECORD_HEADER FileRecord,
PNTFS_ATTR_RECORD AttributeAddress, PNTFS_ATTR_RECORD AttributeAddress,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PULONGLONG ParentMftIndex) PULONGLONG ParentMftIndex,
BOOLEAN CaseSensitive)
{ {
ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR); ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
PFILENAME_ATTRIBUTE FileNameAttribute; PFILENAME_ATTRIBUTE FileNameAttribute;
@ -178,7 +183,13 @@ AddFileName(PFILE_RECORD_HEADER FileRecord,
if(Remaining.Length != 0) if(Remaining.Length != 0)
RtlCopyUnicodeString(&FilenameNoPath, &Remaining); RtlCopyUnicodeString(&FilenameNoPath, &Remaining);
Status = NtfsFindMftRecord(DeviceExt, CurrentMFTIndex, &Current, &FirstEntry, FALSE, &CurrentMFTIndex); Status = NtfsFindMftRecord(DeviceExt,
CurrentMFTIndex,
&Current,
&FirstEntry,
FALSE,
&CurrentMFTIndex,
CaseSensitive);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
break; break;

View file

@ -246,6 +246,7 @@ NTSTATUS
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt, NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PWSTR FileName, PWSTR FileName,
BOOLEAN CaseSensitive,
PNTFS_FCB * FoundFCB) PNTFS_FCB * FoundFCB)
{ {
PNTFS_FCB ParentFcb; PNTFS_FCB ParentFcb;
@ -253,7 +254,12 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
NTSTATUS Status; NTSTATUS Status;
PWSTR AbsFileName = NULL; PWSTR AbsFileName = NULL;
DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB); DPRINT1("NtfsOpenFile(%p, %p, %S, %s, %p)\n",
DeviceExt,
FileObject,
FileName,
CaseSensitive ? "TRUE" : "FALSE",
FoundFCB);
*FoundFCB = NULL; *FoundFCB = NULL;
@ -285,7 +291,8 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
Status = NtfsGetFCBForFile(DeviceExt, Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb, &ParentFcb,
&Fcb, &Fcb,
FileName); FileName,
CaseSensitive);
if (ParentFcb != NULL) if (ParentFcb != NULL)
{ {
NtfsReleaseFCB(DeviceExt, NtfsReleaseFCB(DeviceExt,
@ -412,6 +419,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
Status = NtfsOpenFile(DeviceExt, Status = NtfsOpenFile(DeviceExt,
FileObject, FileObject,
((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer), ((RequestedOptions & FILE_OPEN_BY_FILE_ID) ? FullPath.Buffer : FileObject->FileName.Buffer),
(Stack->Flags & SL_CASE_SENSITIVE),
&Fcb); &Fcb);
if (RequestedOptions & FILE_OPEN_BY_FILE_ID) if (RequestedOptions & FILE_OPEN_BY_FILE_ID)

View file

@ -627,7 +627,8 @@ NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
&Ccb->Entry, &Ccb->Entry,
&FileRecord, &FileRecord,
&MFTRecord, &MFTRecord,
Fcb->MFTIndex); Fcb->MFTIndex,
(Stack->Flags & SL_CASE_SENSITIVE));
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {

View file

@ -506,6 +506,7 @@ static NTSTATUS
NtfsDirFindFile(PNTFS_VCB Vcb, NtfsDirFindFile(PNTFS_VCB Vcb,
PNTFS_FCB DirectoryFcb, PNTFS_FCB DirectoryFcb,
PWSTR FileToFind, PWSTR FileToFind,
BOOLEAN CaseSensitive,
PNTFS_FCB *FoundFCB) PNTFS_FCB *FoundFCB)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -517,7 +518,12 @@ NtfsDirFindFile(PNTFS_VCB Vcb,
PNTFS_ATTR_CONTEXT DataContext; PNTFS_ATTR_CONTEXT DataContext;
USHORT Length = 0; USHORT Length = 0;
DPRINT1("NtfsDirFindFile(%p, %p, %S, %p)\n", Vcb, DirectoryFcb, FileToFind, FoundFCB); DPRINT1("NtfsDirFindFile(%p, %p, %S, %s, %p)\n",
Vcb,
DirectoryFcb,
FileToFind,
CaseSensitive ? "TRUE" : "FALSE",
FoundFCB);
*FoundFCB = NULL; *FoundFCB = NULL;
RtlInitUnicodeString(&File, FileToFind); RtlInitUnicodeString(&File, FileToFind);
@ -551,7 +557,7 @@ NtfsDirFindFile(PNTFS_VCB Vcb,
DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon); DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon);
} }
Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &MFTIndex, CurrentDir); Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &MFTIndex, CurrentDir, CaseSensitive);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -587,7 +593,8 @@ NTSTATUS
NtfsGetFCBForFile(PNTFS_VCB Vcb, NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB *pParentFCB, PNTFS_FCB *pParentFCB,
PNTFS_FCB *pFCB, PNTFS_FCB *pFCB,
const PWSTR pFileName) const PWSTR pFileName,
BOOLEAN CaseSensitive)
{ {
NTSTATUS Status; NTSTATUS Status;
WCHAR pathName [MAX_PATH]; WCHAR pathName [MAX_PATH];
@ -596,11 +603,12 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB FCB; PNTFS_FCB FCB;
PNTFS_FCB parentFCB; PNTFS_FCB parentFCB;
DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S')\n", DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S', %s)\n",
Vcb, Vcb,
pParentFCB, pParentFCB,
pFCB, pFCB,
pFileName); pFileName,
CaseSensitive ? "TRUE" : "FALSE");
/* Dummy code */ /* Dummy code */
// FCB = NtfsOpenRootFCB(Vcb); // FCB = NtfsOpenRootFCB(Vcb);
@ -677,7 +685,7 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
NtfsGetNextPathElement(currentElement) - currentElement); NtfsGetNextPathElement(currentElement) - currentElement);
DPRINT(" elementName:%S\n", elementName); DPRINT(" elementName:%S\n", elementName);
Status = NtfsDirFindFile(Vcb, parentFCB, elementName, &FCB); Status = NtfsDirFindFile(Vcb, parentFCB, elementName, CaseSensitive, &FCB);
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{ {
*pParentFCB = parentFCB; *pParentFCB = parentFCB;

View file

@ -415,6 +415,10 @@ NtfsQueryInformation(PNTFS_IRP_CONTEXT IrpContext)
* @param IrpFlags * @param IrpFlags
* ULONG describing the flags of the original IRP request (Irp->Flags). * ULONG describing the flags of the original IRP request (Irp->Flags).
* *
* @param CaseSensitive
* Boolean indicating if the function should operate in case-sensitive mode. This will be TRUE
* if an application opened the file with the FILE_FLAG_POSIX_SEMANTICS flag.
*
* @param NewFileSize * @param NewFileSize
* Pointer to a LARGE_INTEGER which indicates the new end of file (file size). * Pointer to a LARGE_INTEGER which indicates the new end of file (file size).
* *
@ -436,6 +440,7 @@ NtfsSetEndOfFile(PNTFS_FCB Fcb,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
ULONG IrpFlags, ULONG IrpFlags,
BOOLEAN CaseSensitive,
PLARGE_INTEGER NewFileSize) PLARGE_INTEGER NewFileSize)
{ {
LARGE_INTEGER CurrentFileSize; LARGE_INTEGER CurrentFileSize;
@ -545,7 +550,13 @@ NtfsSetEndOfFile(PNTFS_FCB Fcb,
AllocationSize = ROUND_UP(NewFileSize->QuadPart, Fcb->Vcb->NtfsInfo.BytesPerCluster); AllocationSize = ROUND_UP(NewFileSize->QuadPart, Fcb->Vcb->NtfsInfo.BytesPerCluster);
Status = UpdateFileNameRecord(Fcb->Vcb, ParentMFTId, &filename, FALSE, NewFileSize->QuadPart, AllocationSize); Status = UpdateFileNameRecord(Fcb->Vcb,
ParentMFTId,
&filename,
FALSE,
NewFileSize->QuadPart,
AllocationSize,
CaseSensitive);
ReleaseAttributeContext(DataContext); ReleaseAttributeContext(DataContext);
ExFreePoolWithTag(FileRecord, TAG_NTFS); ExFreePoolWithTag(FileRecord, TAG_NTFS);
@ -620,7 +631,12 @@ NtfsSetInformation(PNTFS_IRP_CONTEXT IrpContext)
DPRINT1("FIXME: Using hacky method of setting FileAllocationInformation.\n"); DPRINT1("FIXME: Using hacky method of setting FileAllocationInformation.\n");
case FileEndOfFileInformation: case FileEndOfFileInformation:
EndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)SystemBuffer; EndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)SystemBuffer;
Status = NtfsSetEndOfFile(Fcb, FileObject, DeviceExt, Irp->Flags, &EndOfFileInfo->EndOfFile); Status = NtfsSetEndOfFile(Fcb,
FileObject,
DeviceExt,
Irp->Flags,
(Stack->Flags & SL_CASE_SENSITIVE),
&EndOfFileInfo->EndOfFile);
break; break;
// TODO: all other information classes // TODO: all other information classes

View file

@ -1359,7 +1359,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING FileName, PUNICODE_STRING FileName,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG NewDataSize, ULONGLONG NewDataSize,
ULONGLONG NewAllocationSize) ULONGLONG NewAllocationSize,
BOOLEAN CaseSensitive)
{ {
PFILE_RECORD_HEADER MftRecord; PFILE_RECORD_HEADER MftRecord;
PNTFS_ATTR_CONTEXT IndexRootCtx; PNTFS_ATTR_CONTEXT IndexRootCtx;
@ -1369,7 +1370,14 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
NTSTATUS Status; NTSTATUS Status;
ULONG CurrentEntry = 0; ULONG CurrentEntry = 0;
DPRINT("UpdateFileNameRecord(%p, %I64d, %wZ, %u, %I64u, %I64u)\n", Vcb, ParentMFTIndex, FileName, DirSearch, NewDataSize, NewAllocationSize); DPRINT("UpdateFileNameRecord(%p, %I64d, %wZ, %u, %I64u, %I64u, %s)\n",
Vcb,
ParentMFTIndex,
FileName,
DirSearch,
NewDataSize,
NewAllocationSize,
CaseSensitive ? "TRUE" : "FALSE");
MftRecord = ExAllocatePoolWithTag(NonPagedPool, MftRecord = ExAllocatePoolWithTag(NonPagedPool,
Vcb->NtfsInfo.BytesPerFileRecord, Vcb->NtfsInfo.BytesPerFileRecord,
@ -1421,7 +1429,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
&CurrentEntry, &CurrentEntry,
DirSearch, DirSearch,
NewDataSize, NewDataSize,
NewAllocationSize); NewAllocationSize,
CaseSensitive);
ReleaseAttributeContext(IndexRootCtx); ReleaseAttributeContext(IndexRootCtx);
ExFreePoolWithTag(IndexRecord, TAG_NTFS); ExFreePoolWithTag(IndexRecord, TAG_NTFS);
@ -1447,7 +1456,8 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
PULONG CurrentEntry, PULONG CurrentEntry,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG NewDataSize, ULONGLONG NewDataSize,
ULONGLONG NewAllocatedSize) ULONGLONG NewAllocatedSize,
BOOLEAN CaseSensitive)
{ {
NTSTATUS Status; NTSTATUS Status;
ULONG RecordOffset; ULONG RecordOffset;
@ -1466,7 +1476,7 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) > 0x10 && if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) > 0x10 &&
*CurrentEntry >= *StartEntry && *CurrentEntry >= *StartEntry &&
IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS && IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS &&
CompareFileName(FileName, IndexEntry, DirSearch)) CompareFileName(FileName, IndexEntry, DirSearch, CaseSensitive))
{ {
*StartEntry = *CurrentEntry; *StartEntry = *CurrentEntry;
IndexEntry->FileName.DataSize = NewDataSize; IndexEntry->FileName.DataSize = NewDataSize;
@ -1517,7 +1527,19 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries); LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries);
ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize)); ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize));
Status = UpdateIndexEntryFileNameSize(NULL, NULL, NULL, 0, FirstEntry, LastEntry, FileName, StartEntry, CurrentEntry, DirSearch, NewDataSize, NewAllocatedSize); Status = UpdateIndexEntryFileNameSize(NULL,
NULL,
NULL,
0,
FirstEntry,
LastEntry,
FileName,
StartEntry,
CurrentEntry,
DirSearch,
NewDataSize,
NewAllocatedSize,
CaseSensitive);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
// write the index record back to disk // write the index record back to disk
@ -1827,7 +1849,8 @@ ReadLCN(PDEVICE_EXTENSION Vcb,
BOOLEAN BOOLEAN
CompareFileName(PUNICODE_STRING FileName, CompareFileName(PUNICODE_STRING FileName,
PINDEX_ENTRY_ATTRIBUTE IndexEntry, PINDEX_ENTRY_ATTRIBUTE IndexEntry,
BOOLEAN DirSearch) BOOLEAN DirSearch,
BOOLEAN CaseSensitive)
{ {
BOOLEAN Ret, Alloc = FALSE; BOOLEAN Ret, Alloc = FALSE;
UNICODE_STRING EntryName; UNICODE_STRING EntryName;
@ -1839,7 +1862,7 @@ CompareFileName(PUNICODE_STRING FileName,
if (DirSearch) if (DirSearch)
{ {
UNICODE_STRING IntFileName; UNICODE_STRING IntFileName;
if (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX) if (!CaseSensitive)
{ {
NT_VERIFY(NT_SUCCESS(RtlUpcaseUnicodeString(&IntFileName, FileName, TRUE))); NT_VERIFY(NT_SUCCESS(RtlUpcaseUnicodeString(&IntFileName, FileName, TRUE)));
Alloc = TRUE; Alloc = TRUE;
@ -1849,7 +1872,7 @@ CompareFileName(PUNICODE_STRING FileName,
IntFileName = *FileName; IntFileName = *FileName;
} }
Ret = FsRtlIsNameInExpression(&IntFileName, &EntryName, (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX), NULL); Ret = FsRtlIsNameInExpression(&IntFileName, &EntryName, !CaseSensitive, NULL);
if (Alloc) if (Alloc)
{ {
@ -1860,7 +1883,7 @@ CompareFileName(PUNICODE_STRING FileName,
} }
else else
{ {
return (RtlCompareUnicodeString(FileName, &EntryName, (IndexEntry->FileName.NameType != NTFS_FILE_NAME_POSIX)) == 0); return (RtlCompareUnicodeString(FileName, &EntryName, !CaseSensitive) == 0);
} }
} }
@ -1900,6 +1923,7 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
PULONG StartEntry, PULONG StartEntry,
PULONG CurrentEntry, PULONG CurrentEntry,
BOOLEAN DirSearch, BOOLEAN DirSearch,
BOOLEAN CaseSensitive,
ULONGLONG *OutMFTIndex) ULONGLONG *OutMFTIndex)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -1909,7 +1933,19 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
ULONGLONG IndexAllocationSize; ULONGLONG IndexAllocationSize;
PINDEX_BUFFER IndexBuffer; PINDEX_BUFFER IndexBuffer;
DPRINT("BrowseIndexEntries(%p, %p, %p, %u, %p, %p, %wZ, %u, %u, %u, %p)\n", Vcb, MftRecord, IndexRecord, IndexBlockSize, FirstEntry, LastEntry, FileName, *StartEntry, *CurrentEntry, DirSearch, OutMFTIndex); DPRINT("BrowseIndexEntries(%p, %p, %p, %u, %p, %p, %wZ, %u, %u, %s, %s, %p)\n",
Vcb,
MftRecord,
IndexRecord,
IndexBlockSize,
FirstEntry,
LastEntry,
FileName,
*StartEntry,
*CurrentEntry,
DirSearch ? "TRUE" : "FALSE",
CaseSensitive ? "TRUE" : "FALSE",
OutMFTIndex);
IndexEntry = FirstEntry; IndexEntry = FirstEntry;
while (IndexEntry < LastEntry && while (IndexEntry < LastEntry &&
@ -1918,7 +1954,7 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) >= 0x10 && if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) >= 0x10 &&
*CurrentEntry >= *StartEntry && *CurrentEntry >= *StartEntry &&
IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS && IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS &&
CompareFileName(FileName, IndexEntry, DirSearch)) CompareFileName(FileName, IndexEntry, DirSearch, CaseSensitive))
{ {
*StartEntry = *CurrentEntry; *StartEntry = *CurrentEntry;
*OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK); *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
@ -1967,7 +2003,18 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb,
LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries); LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries);
ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize)); ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize));
Status = BrowseIndexEntries(NULL, NULL, NULL, 0, FirstEntry, LastEntry, FileName, StartEntry, CurrentEntry, DirSearch, OutMFTIndex); Status = BrowseIndexEntries(NULL,
NULL,
NULL,
0,
FirstEntry,
LastEntry,
FileName,
StartEntry,
CurrentEntry,
DirSearch,
CaseSensitive,
OutMFTIndex);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
break; break;
@ -1984,7 +2031,8 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING FileName, PUNICODE_STRING FileName,
PULONG FirstEntry, PULONG FirstEntry,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG *OutMFTIndex) ULONGLONG *OutMFTIndex,
BOOLEAN CaseSensitive)
{ {
PFILE_RECORD_HEADER MftRecord; PFILE_RECORD_HEADER MftRecord;
PNTFS_ATTR_CONTEXT IndexRootCtx; PNTFS_ATTR_CONTEXT IndexRootCtx;
@ -2036,7 +2084,18 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
DPRINT("IndexRecordSize: %x IndexBlockSize: %x\n", Vcb->NtfsInfo.BytesPerIndexRecord, IndexRoot->SizeOfEntry); DPRINT("IndexRecordSize: %x IndexBlockSize: %x\n", Vcb->NtfsInfo.BytesPerIndexRecord, IndexRoot->SizeOfEntry);
Status = BrowseIndexEntries(Vcb, MftRecord, IndexRecord, IndexRoot->SizeOfEntry, IndexEntry, IndexEntryEnd, FileName, FirstEntry, &CurrentEntry, DirSearch, OutMFTIndex); Status = BrowseIndexEntries(Vcb,
MftRecord,
IndexRecord,
IndexRoot->SizeOfEntry,
IndexEntry,
IndexEntryEnd,
FileName,
FirstEntry,
&CurrentEntry,
DirSearch,
CaseSensitive,
OutMFTIndex);
ExFreePoolWithTag(IndexRecord, TAG_NTFS); ExFreePoolWithTag(IndexRecord, TAG_NTFS);
ExFreePoolWithTag(MftRecord, TAG_NTFS); ExFreePoolWithTag(MftRecord, TAG_NTFS);
@ -2049,7 +2108,8 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING PathName, PUNICODE_STRING PathName,
PFILE_RECORD_HEADER *FileRecord, PFILE_RECORD_HEADER *FileRecord,
PULONGLONG MFTIndex, PULONGLONG MFTIndex,
ULONGLONG CurrentMFTIndex) ULONGLONG CurrentMFTIndex,
BOOLEAN CaseSensitive)
{ {
UNICODE_STRING Current, Remaining; UNICODE_STRING Current, Remaining;
NTSTATUS Status; NTSTATUS Status;
@ -2063,7 +2123,7 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
{ {
DPRINT("Current: %wZ\n", &Current); DPRINT("Current: %wZ\n", &Current);
Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, &Current, &FirstEntry, FALSE, &CurrentMFTIndex); Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, &Current, &FirstEntry, FALSE, &CurrentMFTIndex, CaseSensitive);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
return Status; return Status;
@ -2099,9 +2159,10 @@ NTSTATUS
NtfsLookupFile(PDEVICE_EXTENSION Vcb, NtfsLookupFile(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING PathName, PUNICODE_STRING PathName,
PFILE_RECORD_HEADER *FileRecord, PFILE_RECORD_HEADER *FileRecord,
PULONGLONG MFTIndex) PULONGLONG MFTIndex,
BOOLEAN CaseSensitive)
{ {
return NtfsLookupFileAt(Vcb, PathName, FileRecord, MFTIndex, NTFS_FILE_ROOT); return NtfsLookupFileAt(Vcb, PathName, FileRecord, MFTIndex, NTFS_FILE_ROOT, CaseSensitive);
} }
/** /**
@ -2150,13 +2211,21 @@ NtfsFindFileAt(PDEVICE_EXTENSION Vcb,
PULONG FirstEntry, PULONG FirstEntry,
PFILE_RECORD_HEADER *FileRecord, PFILE_RECORD_HEADER *FileRecord,
PULONGLONG MFTIndex, PULONGLONG MFTIndex,
ULONGLONG CurrentMFTIndex) ULONGLONG CurrentMFTIndex,
BOOLEAN CaseSensitive)
{ {
NTSTATUS Status; NTSTATUS Status;
DPRINT("NtfsFindFileAt(%p, %wZ, %u, %p, %p, %I64x)\n", Vcb, SearchPattern, *FirstEntry, FileRecord, MFTIndex, CurrentMFTIndex); DPRINT("NtfsFindFileAt(%p, %wZ, %u, %p, %p, %I64x, %s)\n",
Vcb,
SearchPattern,
*FirstEntry,
FileRecord,
MFTIndex,
CurrentMFTIndex,
(CaseSensitive ? "TRUE" : "FALSE"));
Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, SearchPattern, FirstEntry, TRUE, &CurrentMFTIndex); Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, SearchPattern, FirstEntry, TRUE, &CurrentMFTIndex, CaseSensitive);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("NtfsFindFileAt: NtfsFindMftRecord() failed with status 0x%08lx\n", Status); DPRINT("NtfsFindFileAt: NtfsFindMftRecord() failed with status 0x%08lx\n", Status);

View file

@ -781,7 +781,8 @@ NTSTATUS
NtfsGetFCBForFile(PNTFS_VCB Vcb, NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB *pParentFCB, PNTFS_FCB *pParentFCB,
PNTFS_FCB *pFCB, PNTFS_FCB *pFCB,
const PWSTR pFileName); const PWSTR pFileName,
BOOLEAN CaseSensitive);
NTSTATUS NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb, NtfsReadFCBAttribute(PNTFS_VCB Vcb,
@ -811,6 +812,7 @@ NtfsSetEndOfFile(PNTFS_FCB Fcb,
PFILE_OBJECT FileObject, PFILE_OBJECT FileObject,
PDEVICE_EXTENSION DeviceExt, PDEVICE_EXTENSION DeviceExt,
ULONG IrpFlags, ULONG IrpFlags,
BOOLEAN CaseSensitive,
PLARGE_INTEGER NewFileSize); PLARGE_INTEGER NewFileSize);
NTSTATUS NTSTATUS
@ -892,7 +894,8 @@ AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord);
BOOLEAN BOOLEAN
CompareFileName(PUNICODE_STRING FileName, CompareFileName(PUNICODE_STRING FileName,
PINDEX_ENTRY_ATTRIBUTE IndexEntry, PINDEX_ENTRY_ATTRIBUTE IndexEntry,
BOOLEAN DirSearch); BOOLEAN DirSearch,
BOOLEAN CaseSensitive);
NTSTATUS NTSTATUS
ReadFileRecord(PDEVICE_EXTENSION Vcb, ReadFileRecord(PDEVICE_EXTENSION Vcb,
@ -911,7 +914,8 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb,
PULONG CurrentEntry, PULONG CurrentEntry,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG NewDataSize, ULONGLONG NewDataSize,
ULONGLONG NewAllocatedSize); ULONGLONG NewAllocatedSize,
BOOLEAN CaseSensitive);
NTSTATUS NTSTATUS
UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
@ -919,7 +923,8 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING FileName, PUNICODE_STRING FileName,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG NewDataSize, ULONGLONG NewDataSize,
ULONGLONG NewAllocationSize); ULONGLONG NewAllocationSize,
BOOLEAN CaseSensitive);
NTSTATUS NTSTATUS
UpdateFileRecord(PDEVICE_EXTENSION Vcb, UpdateFileRecord(PDEVICE_EXTENSION Vcb,
@ -973,7 +978,8 @@ NtfsLookupFileAt(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING PathName, PUNICODE_STRING PathName,
PFILE_RECORD_HEADER *FileRecord, PFILE_RECORD_HEADER *FileRecord,
PULONGLONG MFTIndex, PULONGLONG MFTIndex,
ULONGLONG CurrentMFTIndex); ULONGLONG CurrentMFTIndex,
BOOLEAN CaseSensitive);
VOID VOID
NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb, NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb,
@ -985,7 +991,8 @@ NtfsFindFileAt(PDEVICE_EXTENSION Vcb,
PULONG FirstEntry, PULONG FirstEntry,
PFILE_RECORD_HEADER *FileRecord, PFILE_RECORD_HEADER *FileRecord,
PULONGLONG MFTIndex, PULONGLONG MFTIndex,
ULONGLONG CurrentMFTIndex); ULONGLONG CurrentMFTIndex,
BOOLEAN CaseSensitive);
NTSTATUS NTSTATUS
NtfsFindMftRecord(PDEVICE_EXTENSION Vcb, NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
@ -993,7 +1000,8 @@ NtfsFindMftRecord(PDEVICE_EXTENSION Vcb,
PUNICODE_STRING FileName, PUNICODE_STRING FileName,
PULONG FirstEntry, PULONG FirstEntry,
BOOLEAN DirSearch, BOOLEAN DirSearch,
ULONGLONG *OutMFTIndex); ULONGLONG *OutMFTIndex,
BOOLEAN CaseSensitive);
/* misc.c */ /* misc.c */

View file

@ -283,6 +283,10 @@ NtfsRead(PNTFS_IRP_CONTEXT IrpContext)
* @param IrpFlags * @param IrpFlags
* TODO: flags are presently ignored in code. * TODO: flags are presently ignored in code.
* *
* @param CaseSensitive
* Boolean indicating if the function should operate in case-sensitive mode. This will be TRUE
* if an application opened the file with the FILE_FLAG_POSIX_SEMANTICS flag.
*
* @param LengthWritten * @param LengthWritten
* Pointer to a ULONG. This ULONG will be set to the number of bytes successfully written. * Pointer to a ULONG. This ULONG will be set to the number of bytes successfully written.
* *
@ -303,6 +307,7 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt,
ULONG Length, ULONG Length,
ULONG WriteOffset, ULONG WriteOffset,
ULONG IrpFlags, ULONG IrpFlags,
BOOLEAN CaseSensitive,
PULONG LengthWritten) PULONG LengthWritten)
{ {
NTSTATUS Status = STATUS_NOT_IMPLEMENTED; NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
@ -312,7 +317,15 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt,
ULONG AttributeOffset; ULONG AttributeOffset;
ULONGLONG StreamSize; ULONGLONG StreamSize;
DPRINT("NtfsWriteFile(%p, %p, %p, %u, %u, %x, %p)\n", DeviceExt, FileObject, Buffer, Length, WriteOffset, IrpFlags, LengthWritten); DPRINT("NtfsWriteFile(%p, %p, %p, %u, %u, %x, %s, %p)\n",
DeviceExt,
FileObject,
Buffer,
Length,
WriteOffset,
IrpFlags,
(CaseSensitive ? "TRUE" : "FALSE"),
LengthWritten);
*LengthWritten = 0; *LengthWritten = 0;
@ -444,7 +457,13 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt,
filename.Length = fileNameAttribute->NameLength * sizeof(WCHAR); filename.Length = fileNameAttribute->NameLength * sizeof(WCHAR);
filename.MaximumLength = filename.Length; filename.MaximumLength = filename.Length;
Status = UpdateFileNameRecord(Fcb->Vcb, ParentMFTId, &filename, FALSE, DataSize.QuadPart, AllocationSize); Status = UpdateFileNameRecord(Fcb->Vcb,
ParentMFTId,
&filename,
FALSE,
DataSize.QuadPart,
AllocationSize,
CaseSensitive);
} }
else else
@ -667,6 +686,7 @@ NtfsWrite(PNTFS_IRP_CONTEXT IrpContext)
Length, Length,
ByteOffset.LowPart, ByteOffset.LowPart,
Irp->Flags, Irp->Flags,
(IrpContext->Stack->Flags & SL_CASE_SENSITIVE),
&ReturnedWriteLength); &ReturnedWriteLength);
IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Status = Status;