Author: ion Date: Thu Jul 27 04:13:14 2006 New Revision: 23302
URL: http://svn.reactos.org/svn/reactos?rev=23302&view=rev Log: - Fix multiple bugs in VfatGetNameInformation: * Return the file name length even if the buffer is too small, that's the whole point of the "Query length before comitting a buffer" principle. * FSDs are not supposed to null-terminate the buffer, nor expect the caller to send a buffer large enough for null-termination. * Added a hack in IopQueryFile to handle another VFAT bug which makes it return the total number of bytes written in IoStatus.Information instead of the total number of bytes *left untouched*.There are probably many other broken things due to this. - Fix some length calculation bugs in IopQueryFile.
Modified: trunk/reactos/drivers/filesystems/vfat/finfo.c trunk/reactos/ntoskrnl/io/iomgr/file.c trunk/reactos/ntoskrnl/ob/obname.c
Modified: trunk/reactos/drivers/filesystems/vfat/finfo.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filesystems/vfat/fi... ============================================================================== --- trunk/reactos/drivers/filesystems/vfat/finfo.c (original) +++ trunk/reactos/drivers/filesystems/vfat/finfo.c Thu Jul 27 04:13:14 2006 @@ -341,14 +341,13 @@ ASSERT(NameInfo != NULL); ASSERT(FCB != NULL);
- if (*BufferLength < sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR)) + NameInfo->FileNameLength = FCB->PathNameU.Length; + if (*BufferLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length) return STATUS_BUFFER_OVERFLOW;
- NameInfo->FileNameLength = FCB->PathNameU.Length; RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length); - NameInfo->FileName[FCB->PathNameU.Length / sizeof(WCHAR)] = 0; - - *BufferLength -= (sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR)); + + *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length);
return STATUS_SUCCESS; }
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?re... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/file.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/file.c Thu Jul 27 04:13:14 2006 @@ -915,7 +915,7 @@ LocalInfo, Length, &LocalReturnLength); - if (!NT_SUCCESS (Status)) + if (!NT_SUCCESS(Status)) { /* Free the buffer and fail */ ExFreePool(LocalInfo); @@ -935,6 +935,14 @@ /* Advance in buffer */ p += (LocalInfo->Name.Length / sizeof(WCHAR));
+ /* Check if this already filled our buffer */ + if (LocalReturnLength > Length) + { + /* Free the buffer and fail */ + ExFreePool(LocalInfo); + return STATUS_BUFFER_OVERFLOW; + } + /* Now get the file name buffer and check the length needed */ LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo; FileLength = Length - @@ -944,7 +952,7 @@ /* Query the File name */ Status = IoQueryFileInformation(FileObject, FileNameInformation, - Length, + FileLength, LocalFileInfo, &LocalReturnLength); if (NT_ERROR(Status)) @@ -953,6 +961,9 @@ ExFreePool(LocalInfo); return Status; } + + /* ROS HACK. VFAT SUCKS */ + if (NT_WARNING(Status)) LocalReturnLength = FileLength;
/* Now calculate the new lenghts left */ FileLength = LocalReturnLength - @@ -972,7 +983,7 @@
/* Setup the length and maximum length */ FileLength = (ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo; - ObjectNameInfo->Name.Length = Length - sizeof(OBJECT_NAME_INFORMATION); + ObjectNameInfo->Name.Length = FileLength - sizeof(OBJECT_NAME_INFORMATION); ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length + sizeof(UNICODE_NULL);
Modified: trunk/reactos/ntoskrnl/ob/obname.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obname.c?rev=23... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obname.c (original) +++ trunk/reactos/ntoskrnl/ob/obname.c Thu Jul 27 04:13:14 2006 @@ -620,7 +620,7 @@ }
/* Check if the object doesn't even have a name */ - if (!LocalInfo || !LocalInfo->Name.Buffer) + if (!(LocalInfo) || !(LocalInfo->Name.Buffer)) { /* We're returning the name structure */ *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);