Author: ion
Date: Wed Jul 5 03:31:42 2006
New Revision: 22853
URL:
http://svn.reactos.org/svn/reactos?rev=22853&view=rev
Log:
- Fix IopQueryNameFile to properly validate and calculate lengths at each step of the way
and to support incomplete buffers. Previously, dangerous assumptions were made about the
buffers and the actual required length was never returned.
Modified:
trunk/reactos/ntoskrnl/io/iomgr/file.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c Wed Jul 5 03:31:42 2006
@@ -463,61 +463,97 @@
}
NTSTATUS
-STDCALL
-IopQueryNameFile(PVOID ObjectBody,
+NTAPI
+IopQueryNameFile(IN PVOID ObjectBody,
IN BOOLEAN HasName,
- POBJECT_NAME_INFORMATION ObjectNameInfo,
- ULONG Length,
- PULONG ReturnLength,
+ OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
+ IN ULONG Length,
+ OUT PULONG ReturnLength,
IN KPROCESSOR_MODE PreviousMode)
{
POBJECT_NAME_INFORMATION LocalInfo;
- PFILE_OBJECT FileObject;
- ULONG LocalReturnLength;
+ PFILE_NAME_INFORMATION LocalFileInfo;
+ PFILE_OBJECT FileObject = (PFILE_OBJECT)ObjectBody;
+ ULONG LocalReturnLength, FileLength;
NTSTATUS Status;
-
- DPRINT1("IopQueryNameFile() called\n");
-
- FileObject = (PFILE_OBJECT)ObjectBody;
+ PWCHAR p;
+
+ /* Validate length */
+ if (Length < sizeof(OBJECT_NAME_INFORMATION))
+ {
+ /* Wrong length, fail */
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
/* Allocate Buffer */
- LocalInfo = ExAllocatePool(PagedPool,
- sizeof(OBJECT_NAME_INFORMATION) +
- MAX_PATH * sizeof(WCHAR));
- if (LocalInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;
+ LocalInfo = ExAllocatePoolWithTag(PagedPool, Length, TAG_IO);
+ if (!LocalInfo) return STATUS_INSUFFICIENT_RESOURCES;
/* Query the name */
Status = ObQueryNameString(FileObject->DeviceObject,
LocalInfo,
- MAX_PATH * sizeof(WCHAR),
+ Length,
&LocalReturnLength);
if (!NT_SUCCESS (Status))
{
- ExFreePool (LocalInfo);
+ /* Free the buffer and fail */
+ ExFreePool(LocalInfo);
return Status;
}
- DPRINT ("Device path: %wZ\n", &LocalInfo->Name);
-
- /* Write Device Path */
- Status = RtlAppendUnicodeStringToString(&ObjectNameInfo->Name,
- &(LocalInfo)->Name);
+
+ /* Copy the information */
+ RtlCopyMemory(ObjectNameInfo,
+ LocalInfo,
+ LocalReturnLength > Length ?
+ Length : LocalReturnLength);
+
+ /* Set buffer pointer */
+ p = (PWCHAR)(ObjectNameInfo + 1);
+ ObjectNameInfo->Name.Buffer = p;
+
+ /* Advance in buffer */
+ p += (LocalInfo->Name.Length / sizeof(WCHAR));
+
+ /* Now get the file name buffer and check the length needed */
+ LocalFileInfo = (PFILE_NAME_INFORMATION)LocalInfo;
+ FileLength = Length -
+ LocalReturnLength +
+ FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
/* Query the File name */
Status = IoQueryFileInformation(FileObject,
FileNameInformation,
- LocalReturnLength,
- LocalInfo,
- NULL);
- if (Status != STATUS_SUCCESS)
- {
+ Length,
+ LocalFileInfo,
+ &LocalReturnLength);
+ if (NT_ERROR(Status))
+ {
+ /* Fail on errors only, allow warnings */
ExFreePool(LocalInfo);
return Status;
}
- /* Write the Name */
- Status = RtlAppendUnicodeToString(&ObjectNameInfo->Name,
- ((PFILE_NAME_INFORMATION)LocalInfo)->FileName);
- DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
+ /* Now calculate the new lenghts left */
+ FileLength = LocalReturnLength -
+ FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
+ LocalReturnLength = (ULONG_PTR)p -
+ (ULONG_PTR)ObjectNameInfo +
+ LocalFileInfo->FileNameLength;
+
+ /* Write the Name and null-terminate it */
+ RtlMoveMemory(p, LocalFileInfo->FileName, FileLength);
+ p += (FileLength / sizeof(WCHAR));
+ *p = UNICODE_NULL;
+ LocalReturnLength += sizeof(UNICODE_NULL);
+
+ /* Return the length needed */
+ *ReturnLength = LocalReturnLength;
+
+ /* Setup the length and maximum length */
+ FileLength = (ULONG_PTR)p - (ULONG_PTR)ObjectNameInfo;
+ ObjectNameInfo->Name.Length = Length - sizeof(OBJECT_NAME_INFORMATION);
+ ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length +
+ sizeof(UNICODE_NULL);
/* Free buffer and return */
ExFreePool(LocalInfo);