3 * Copyright (C) 2002 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * FILE: drivers/filesystem/ntfs/dirctl.c
22 * PURPOSE: NTFS filesystem driver
23 * PROGRAMMERS: Eric Kohl
24 * Hervé Poussineau (hpoussin@reactos.org)
25 * Pierre Schweitzer (pierre@reactos.org)
28 /* INCLUDES *****************************************************************/
35 /* FUNCTIONS ****************************************************************/
38 * FUNCTION: Retrieve the standard file information
42 NtfsGetStandardInformation(PNTFS_FCB Fcb
,
43 PDEVICE_OBJECT DeviceObject
,
44 PFILE_STANDARD_INFORMATION StandardInfo
,
47 UNREFERENCED_PARAMETER(DeviceObject
);
49 DPRINT1("NtfsGetStandardInformation(%p, %p, %p, %p)\n", Fcb
, DeviceObject
, StandardInfo
, BufferLength
);
51 if (*BufferLength
< sizeof(FILE_STANDARD_INFORMATION
))
52 return STATUS_BUFFER_TOO_SMALL
;
55 ASSERT(StandardInfo
!= NULL
);
58 RtlZeroMemory(StandardInfo
,
59 sizeof(FILE_STANDARD_INFORMATION
));
61 StandardInfo
->AllocationSize
= Fcb
->RFCB
.AllocationSize
;
62 StandardInfo
->EndOfFile
= Fcb
->RFCB
.FileSize
;
63 StandardInfo
->NumberOfLinks
= Fcb
->LinkCount
;
64 StandardInfo
->DeletePending
= FALSE
;
65 StandardInfo
->Directory
= NtfsFCBIsDirectory(Fcb
);
67 *BufferLength
-= sizeof(FILE_STANDARD_INFORMATION
);
69 return STATUS_SUCCESS
;
75 NtfsGetPositionInformation(PFILE_OBJECT FileObject
,
76 PFILE_POSITION_INFORMATION PositionInfo
,
79 DPRINT1("NtfsGetPositionInformation(%p, %p, %p)\n", FileObject
, PositionInfo
, BufferLength
);
81 if (*BufferLength
< sizeof(FILE_POSITION_INFORMATION
))
82 return STATUS_BUFFER_TOO_SMALL
;
84 PositionInfo
->CurrentByteOffset
.QuadPart
= FileObject
->CurrentByteOffset
.QuadPart
;
86 DPRINT("Getting position %I64x\n",
87 PositionInfo
->CurrentByteOffset
.QuadPart
);
89 *BufferLength
-= sizeof(FILE_POSITION_INFORMATION
);
91 return STATUS_SUCCESS
;
97 NtfsGetBasicInformation(PFILE_OBJECT FileObject
,
99 PDEVICE_OBJECT DeviceObject
,
100 PFILE_BASIC_INFORMATION BasicInfo
,
103 PFILENAME_ATTRIBUTE FileName
= &Fcb
->Entry
;
105 DPRINT1("NtfsGetBasicInformation(%p, %p, %p, %p, %p)\n", FileObject
, Fcb
, DeviceObject
, BasicInfo
, BufferLength
);
107 if (*BufferLength
< sizeof(FILE_BASIC_INFORMATION
))
108 return STATUS_BUFFER_TOO_SMALL
;
110 BasicInfo
->CreationTime
.QuadPart
= FileName
->CreationTime
;
111 BasicInfo
->LastAccessTime
.QuadPart
= FileName
->LastAccessTime
;
112 BasicInfo
->LastWriteTime
.QuadPart
= FileName
->LastWriteTime
;
113 BasicInfo
->ChangeTime
.QuadPart
= FileName
->ChangeTime
;
115 NtfsFileFlagsToAttributes(FileName
->FileAttributes
, &BasicInfo
->FileAttributes
);
117 *BufferLength
-= sizeof(FILE_BASIC_INFORMATION
);
119 return STATUS_SUCCESS
;
124 * FUNCTION: Retrieve the file name information
128 NtfsGetNameInformation(PFILE_OBJECT FileObject
,
130 PDEVICE_OBJECT DeviceObject
,
131 PFILE_NAME_INFORMATION NameInfo
,
136 UNREFERENCED_PARAMETER(FileObject
);
137 UNREFERENCED_PARAMETER(DeviceObject
);
139 DPRINT1("NtfsGetNameInformation(%p, %p, %p, %p, %p)\n", FileObject
, Fcb
, DeviceObject
, NameInfo
, BufferLength
);
141 ASSERT(NameInfo
!= NULL
);
144 /* If buffer can't hold at least the file name length, bail out */
145 if (*BufferLength
< (ULONG
)FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]))
146 return STATUS_BUFFER_TOO_SMALL
;
148 /* Save file name length, and as much file len, as buffer length allows */
149 NameInfo
->FileNameLength
= wcslen(Fcb
->PathName
) * sizeof(WCHAR
);
151 /* Calculate amount of bytes to copy not to overflow the buffer */
152 BytesToCopy
= min(NameInfo
->FileNameLength
,
153 *BufferLength
- FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]));
155 /* Fill in the bytes */
156 RtlCopyMemory(NameInfo
->FileName
, Fcb
->PathName
, BytesToCopy
);
158 /* Check if we could write more but are not able to */
159 if (*BufferLength
< NameInfo
->FileNameLength
+ (ULONG
)FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]))
161 /* Return number of bytes written */
162 *BufferLength
-= FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + BytesToCopy
;
163 return STATUS_BUFFER_OVERFLOW
;
166 /* We filled up as many bytes, as needed */
167 *BufferLength
-= (FIELD_OFFSET(FILE_NAME_INFORMATION
, FileName
[0]) + NameInfo
->FileNameLength
);
169 return STATUS_SUCCESS
;
175 NtfsGetInternalInformation(PNTFS_FCB Fcb
,
176 PFILE_INTERNAL_INFORMATION InternalInfo
,
179 DPRINT1("NtfsGetInternalInformation(%p, %p, %p)\n", Fcb
, InternalInfo
, BufferLength
);
181 ASSERT(InternalInfo
);
184 if (*BufferLength
< sizeof(FILE_INTERNAL_INFORMATION
))
185 return STATUS_BUFFER_TOO_SMALL
;
187 InternalInfo
->IndexNumber
.QuadPart
= Fcb
->MFTIndex
;
189 *BufferLength
-= sizeof(FILE_INTERNAL_INFORMATION
);
191 return STATUS_SUCCESS
;
196 NtfsGetNetworkOpenInformation(PNTFS_FCB Fcb
,
197 PDEVICE_EXTENSION DeviceExt
,
198 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo
,
201 PFILENAME_ATTRIBUTE FileName
= &Fcb
->Entry
;
203 DPRINT1("NtfsGetNetworkOpenInformation(%p, %p, %p, %p)\n", Fcb
, DeviceExt
, NetworkInfo
, BufferLength
);
205 if (*BufferLength
< sizeof(FILE_NETWORK_OPEN_INFORMATION
))
206 return STATUS_BUFFER_TOO_SMALL
;
208 NetworkInfo
->CreationTime
.QuadPart
= FileName
->CreationTime
;
209 NetworkInfo
->LastAccessTime
.QuadPart
= FileName
->LastAccessTime
;
210 NetworkInfo
->LastWriteTime
.QuadPart
= FileName
->LastWriteTime
;
211 NetworkInfo
->ChangeTime
.QuadPart
= FileName
->ChangeTime
;
213 NetworkInfo
->EndOfFile
= Fcb
->RFCB
.FileSize
;
214 NetworkInfo
->AllocationSize
= Fcb
->RFCB
.AllocationSize
;
216 NtfsFileFlagsToAttributes(FileName
->FileAttributes
, &NetworkInfo
->FileAttributes
);
218 *BufferLength
-= sizeof(FILE_NETWORK_OPEN_INFORMATION
);
219 return STATUS_SUCCESS
;
224 NtfsGetSteamInformation(PNTFS_FCB Fcb
,
225 PDEVICE_EXTENSION DeviceExt
,
226 PFILE_STREAM_INFORMATION StreamInfo
,
230 FIND_ATTR_CONTXT Context
;
231 PNTFS_ATTR_RECORD Attribute
;
232 NTSTATUS Status
, BrowseStatus
;
233 PFILE_RECORD_HEADER FileRecord
;
234 PFILE_STREAM_INFORMATION CurrentInfo
= StreamInfo
, Previous
= NULL
;
236 if (*BufferLength
< sizeof(FILE_STREAM_INFORMATION
))
237 return STATUS_BUFFER_TOO_SMALL
;
239 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
240 if (FileRecord
== NULL
)
242 DPRINT1("Not enough memory!\n");
243 return STATUS_INSUFFICIENT_RESOURCES
;
246 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
247 if (!NT_SUCCESS(Status
))
249 DPRINT1("Can't find record!\n");
250 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
254 BrowseStatus
= FindFirstAttribute(&Context
, DeviceExt
, FileRecord
, FALSE
, &Attribute
);
255 while (NT_SUCCESS(BrowseStatus
))
257 if (Attribute
->Type
== AttributeData
)
259 CurrentSize
= FIELD_OFFSET(FILE_STREAM_INFORMATION
, StreamName
) + Attribute
->NameLength
* sizeof(WCHAR
) + wcslen(L
"::$DATA") * sizeof(WCHAR
);
261 if (CurrentSize
> *BufferLength
)
263 Status
= STATUS_BUFFER_OVERFLOW
;
267 CurrentInfo
->NextEntryOffset
= 0;
268 CurrentInfo
->StreamNameLength
= (Attribute
->NameLength
+ wcslen(L
"::$DATA")) * sizeof(WCHAR
);
269 CurrentInfo
->StreamSize
.QuadPart
= AttributeDataLength(Attribute
);
270 CurrentInfo
->StreamAllocationSize
.QuadPart
= AttributeAllocatedLength(Attribute
);
271 CurrentInfo
->StreamName
[0] = L
':';
272 RtlMoveMemory(&CurrentInfo
->StreamName
[1], (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
), CurrentInfo
->StreamNameLength
);
273 RtlMoveMemory(&CurrentInfo
->StreamName
[Attribute
->NameLength
+ 1], L
":$DATA", sizeof(L
":$DATA") - sizeof(UNICODE_NULL
));
275 if (Previous
!= NULL
)
277 Previous
->NextEntryOffset
= (ULONG_PTR
)CurrentInfo
- (ULONG_PTR
)Previous
;
279 Previous
= CurrentInfo
;
280 CurrentInfo
= (PFILE_STREAM_INFORMATION
)((ULONG_PTR
)CurrentInfo
+ CurrentSize
);
281 *BufferLength
-= CurrentSize
;
284 BrowseStatus
= FindNextAttribute(&Context
, &Attribute
);
287 FindCloseAttribute(&Context
);
288 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
292 // Convert enum value to friendly name
294 GetInfoClassName(FILE_INFORMATION_CLASS infoClass
)
296 const PCSTR fileInfoClassNames
[] = { "???????",
297 "FileDirectoryInformation",
298 "FileFullDirectoryInformation",
299 "FileBothDirectoryInformation",
300 "FileBasicInformation",
301 "FileStandardInformation",
302 "FileInternalInformation",
304 "FileAccessInformation",
305 "FileNameInformation",
306 "FileRenameInformation",
307 "FileLinkInformation",
308 "FileNamesInformation",
309 "FileDispositionInformation",
310 "FilePositionInformation",
311 "FileFullEaInformation",
312 "FileModeInformation",
313 "FileAlignmentInformation",
314 "FileAllInformation",
315 "FileAllocationInformation",
316 "FileEndOfFileInformation",
317 "FileAlternateNameInformation",
318 "FileStreamInformation",
319 "FilePipeInformation",
320 "FilePipeLocalInformation",
321 "FilePipeRemoteInformation",
322 "FileMailslotQueryInformation",
323 "FileMailslotSetInformation",
324 "FileCompressionInformation",
325 "FileObjectIdInformation",
326 "FileCompletionInformation",
327 "FileMoveClusterInformation",
328 "FileQuotaInformation",
329 "FileReparsePointInformation",
330 "FileNetworkOpenInformation",
331 "FileAttributeTagInformation",
332 "FileTrackingInformation",
333 "FileIdBothDirectoryInformation",
334 "FileIdFullDirectoryInformation",
335 "FileValidDataLengthInformation",
336 "FileShortNameInformation",
337 "FileIoCompletionNotificationInformation",
338 "FileIoStatusBlockRangeInformation",
339 "FileIoPriorityHintInformation",
340 "FileSfioReserveInformation",
341 "FileSfioVolumeInformation",
342 "FileHardLinkInformation",
343 "FileProcessIdsUsingFileInformation",
344 "FileNormalizedNameInformation",
345 "FileNetworkPhysicalNameInformation",
346 "FileIdGlobalTxDirectoryInformation",
347 "FileIsRemoteDeviceInformation",
348 "FileAttributeCacheInformation",
349 "FileNumaNodeInformation",
350 "FileStandardLinkInformation",
351 "FileRemoteProtocolInformation",
352 "FileReplaceCompletionInformation",
353 "FileMaximumInformation",
354 "FileDirectoryInformation",
355 "FileFullDirectoryInformation",
356 "FileBothDirectoryInformation",
357 "FileBasicInformation",
358 "FileStandardInformation",
359 "FileInternalInformation",
361 "FileAccessInformation",
362 "FileNameInformation",
363 "FileRenameInformation",
364 "FileLinkInformation",
365 "FileNamesInformation",
366 "FileDispositionInformation",
367 "FilePositionInformation",
368 "FileFullEaInformation",
369 "FileModeInformation",
370 "FileAlignmentInformation",
371 "FileAllInformation",
372 "FileAllocationInformation",
373 "FileEndOfFileInformation",
374 "FileAlternateNameInformation",
375 "FileStreamInformation",
376 "FilePipeInformation",
377 "FilePipeLocalInformation",
378 "FilePipeRemoteInformation",
379 "FileMailslotQueryInformation",
380 "FileMailslotSetInformation",
381 "FileCompressionInformation",
382 "FileObjectIdInformation",
383 "FileCompletionInformation",
384 "FileMoveClusterInformation",
385 "FileQuotaInformation",
386 "FileReparsePointInformation",
387 "FileNetworkOpenInformation",
388 "FileAttributeTagInformation",
389 "FileTrackingInformation",
390 "FileIdBothDirectoryInformation",
391 "FileIdFullDirectoryInformation",
392 "FileValidDataLengthInformation",
393 "FileShortNameInformation",
394 "FileIoCompletionNotificationInformation",
395 "FileIoStatusBlockRangeInformation",
396 "FileIoPriorityHintInformation",
397 "FileSfioReserveInformation",
398 "FileSfioVolumeInformation",
399 "FileHardLinkInformation",
400 "FileProcessIdsUsingFileInformation",
401 "FileNormalizedNameInformation",
402 "FileNetworkPhysicalNameInformation",
403 "FileIdGlobalTxDirectoryInformation",
404 "FileIsRemoteDeviceInformation",
405 "FileAttributeCacheInformation",
406 "FileNumaNodeInformation",
407 "FileStandardLinkInformation",
408 "FileRemoteProtocolInformation",
409 "FileReplaceCompletionInformation",
410 "FileMaximumInformation" };
411 return fileInfoClassNames
[infoClass
];
415 * FUNCTION: Retrieve the specified file information
418 NtfsQueryInformation(PNTFS_IRP_CONTEXT IrpContext
)
420 FILE_INFORMATION_CLASS FileInformationClass
;
421 PIO_STACK_LOCATION Stack
;
422 PFILE_OBJECT FileObject
;
427 PDEVICE_OBJECT DeviceObject
;
428 NTSTATUS Status
= STATUS_SUCCESS
;
430 DPRINT1("NtfsQueryInformation(%p)\n", IrpContext
);
432 Irp
= IrpContext
->Irp
;
433 Stack
= IrpContext
->Stack
;
434 DeviceObject
= IrpContext
->DeviceObject
;
435 FileInformationClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
436 FileObject
= IrpContext
->FileObject
;
437 Fcb
= FileObject
->FsContext
;
439 SystemBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
440 BufferLength
= Stack
->Parameters
.QueryFile
.Length
;
442 if (!ExAcquireResourceSharedLite(&Fcb
->MainResource
,
443 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
445 return NtfsMarkIrpContextForQueue(IrpContext
);
448 switch (FileInformationClass
)
450 case FileStandardInformation
:
451 Status
= NtfsGetStandardInformation(Fcb
,
457 case FilePositionInformation
:
458 Status
= NtfsGetPositionInformation(FileObject
,
463 case FileBasicInformation
:
464 Status
= NtfsGetBasicInformation(FileObject
,
471 case FileNameInformation
:
472 Status
= NtfsGetNameInformation(FileObject
,
479 case FileInternalInformation
:
480 Status
= NtfsGetInternalInformation(Fcb
,
485 case FileNetworkOpenInformation
:
486 Status
= NtfsGetNetworkOpenInformation(Fcb
,
487 DeviceObject
->DeviceExtension
,
492 case FileStreamInformation
:
493 Status
= NtfsGetSteamInformation(Fcb
,
494 DeviceObject
->DeviceExtension
,
499 case FileAlternateNameInformation
:
500 case FileAllInformation
:
501 DPRINT1("Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass
));
502 Status
= STATUS_NOT_IMPLEMENTED
;
506 DPRINT1("Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass
));
507 Status
= STATUS_INVALID_PARAMETER
;
510 ExReleaseResourceLite(&Fcb
->MainResource
);
512 if (NT_SUCCESS(Status
))
513 Irp
->IoStatus
.Information
=
514 Stack
->Parameters
.QueryFile
.Length
- BufferLength
;
516 Irp
->IoStatus
.Information
= 0;
522 * @name NtfsSetEndOfFile
525 * Sets the end of file (file size) for a given file.
528 * Pointer to an NTFS_FCB which describes the target file. Fcb->MainResource should have been
529 * acquired with ExAcquireResourceSharedLite().
532 * Pointer to a FILE_OBJECT describing the target file.
535 * Points to the target disk's DEVICE_EXTENSION
538 * ULONG describing the flags of the original IRP request (Irp->Flags).
540 * @param CaseSensitive
541 * Boolean indicating if the function should operate in case-sensitive mode. This will be TRUE
542 * if an application opened the file with the FILE_FLAG_POSIX_SEMANTICS flag.
545 * Pointer to a LARGE_INTEGER which indicates the new end of file (file size).
548 * STATUS_SUCCESS if successful,
549 * STATUS_USER_MAPPED_FILE if trying to truncate a file but MmCanFileBeTruncated() returned false,
550 * STATUS_OBJECT_NAME_NOT_FOUND if there was no $DATA attribute associated with the target file,
551 * STATUS_INVALID_PARAMETER if there was no $FILENAME attribute associated with the target file,
552 * STATUS_INSUFFICIENT_RESOURCES if an allocation failed,
553 * STATUS_ACCESS_DENIED if target file is a volume or if paging is involved.
555 * @remarks As this function sets the size of a file at the file-level
556 * (and not at the attribute level) it's not recommended to use this
557 * function alongside functions that operate on the data attribute directly.
561 NtfsSetEndOfFile(PNTFS_FCB Fcb
,
562 PFILE_OBJECT FileObject
,
563 PDEVICE_EXTENSION DeviceExt
,
565 BOOLEAN CaseSensitive
,
566 PLARGE_INTEGER NewFileSize
)
568 LARGE_INTEGER CurrentFileSize
;
569 PFILE_RECORD_HEADER FileRecord
;
570 PNTFS_ATTR_CONTEXT DataContext
;
571 ULONG AttributeOffset
;
572 NTSTATUS Status
= STATUS_SUCCESS
;
573 ULONGLONG AllocationSize
;
574 PFILENAME_ATTRIBUTE FileNameAttribute
;
575 ULONGLONG ParentMFTId
;
576 UNICODE_STRING FileName
;
579 // Allocate non-paged memory for the file record
580 FileRecord
= ExAllocatePoolWithTag(NonPagedPool
, DeviceExt
->NtfsInfo
.BytesPerFileRecord
, TAG_NTFS
);
581 if (FileRecord
== NULL
)
583 DPRINT1("Couldn't allocate memory for file record!");
584 return STATUS_INSUFFICIENT_RESOURCES
;
587 // read the file record
588 DPRINT("Reading file record...\n");
589 Status
= ReadFileRecord(DeviceExt
, Fcb
->MFTIndex
, FileRecord
);
590 if (!NT_SUCCESS(Status
))
592 // We couldn't get the file's record. Free the memory and return the error
593 DPRINT1("Can't find record for %wS!\n", Fcb
->ObjectName
);
594 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
598 DPRINT("Found record for %wS\n", Fcb
->ObjectName
);
600 CurrentFileSize
.QuadPart
= NtfsGetFileSize(DeviceExt
, FileRecord
, L
"", 0, (PULONGLONG
)&CurrentFileSize
);
602 // Are we trying to decrease the file size?
603 if (NewFileSize
->QuadPart
< CurrentFileSize
.QuadPart
)
605 // Is the file mapped?
606 if (!MmCanFileBeTruncated(FileObject
->SectionObjectPointer
,
609 DPRINT1("Couldn't decrease file size!\n");
610 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
611 return STATUS_USER_MAPPED_FILE
;
615 // Find the attribute with the data stream for our file
616 DPRINT("Finding Data Attribute...\n");
617 Status
= FindAttribute(DeviceExt
,
625 // Did we fail to find the attribute?
626 if (!NT_SUCCESS(Status
))
628 DPRINT1("No '%S' data stream associated with file!\n", Fcb
->Stream
);
629 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
633 // Get the size of the data attribute
634 CurrentFileSize
.QuadPart
= AttributeDataLength(&DataContext
->Record
);
636 // Are we enlarging the attribute?
637 if (NewFileSize
->QuadPart
> CurrentFileSize
.QuadPart
)
639 // is increasing the stream size not allowed?
640 if ((Fcb
->Flags
& FCB_IS_VOLUME
) ||
641 (IrpFlags
& IRP_PAGING_IO
))
643 // TODO - just fail for now
644 ReleaseAttributeContext(DataContext
);
645 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
646 return STATUS_ACCESS_DENIED
;
650 // set the attribute data length
651 Status
= SetAttributeDataLength(FileObject
, Fcb
, DataContext
, AttributeOffset
, FileRecord
, NewFileSize
);
652 if (!NT_SUCCESS(Status
))
654 ReleaseAttributeContext(DataContext
);
655 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
659 // now we need to update this file's size in every directory index entry that references it
660 // TODO: expand to work with every filename / hardlink stored in the file record.
661 FileNameAttribute
= GetBestFileNameFromRecord(Fcb
->Vcb
, FileRecord
);
662 if (FileNameAttribute
== NULL
)
664 DPRINT1("Unable to find FileName attribute associated with file!\n");
665 ReleaseAttributeContext(DataContext
);
666 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
667 return STATUS_INVALID_PARAMETER
;
670 ParentMFTId
= FileNameAttribute
->DirectoryFileReferenceNumber
& NTFS_MFT_MASK
;
672 FileName
.Buffer
= FileNameAttribute
->Name
;
673 FileName
.Length
= FileNameAttribute
->NameLength
* sizeof(WCHAR
);
674 FileName
.MaximumLength
= FileName
.Length
;
676 AllocationSize
= ROUND_UP(NewFileSize
->QuadPart
, Fcb
->Vcb
->NtfsInfo
.BytesPerCluster
);
678 Status
= UpdateFileNameRecord(Fcb
->Vcb
,
682 NewFileSize
->QuadPart
,
686 ReleaseAttributeContext(DataContext
);
687 ExFreePoolWithTag(FileRecord
, TAG_NTFS
);
693 * @name NtfsSetInformation
696 * Sets the specified file information.
699 * Points to an NTFS_IRP_CONTEXT which describes the set operation
702 * STATUS_SUCCESS if successful,
703 * STATUS_NOT_IMPLEMENTED if trying to set an unimplemented information class,
704 * STATUS_USER_MAPPED_FILE if trying to truncate a file but MmCanFileBeTruncated() returned false,
705 * STATUS_OBJECT_NAME_NOT_FOUND if there was no $DATA attribute associated with the target file,
706 * STATUS_INVALID_PARAMETER if there was no $FILENAME attribute associated with the target file,
707 * STATUS_INSUFFICIENT_RESOURCES if an allocation failed,
708 * STATUS_ACCESS_DENIED if target file is a volume or if paging is involved.
710 * @remarks Called by NtfsDispatch() in response to an IRP_MJ_SET_INFORMATION request.
711 * Only the FileEndOfFileInformation InformationClass is fully implemented. FileAllocationInformation
712 * is a hack and not a true implementation, but it's enough to make SetEndOfFile() work.
713 * All other information classes are TODO.
717 NtfsSetInformation(PNTFS_IRP_CONTEXT IrpContext
)
719 FILE_INFORMATION_CLASS FileInformationClass
;
720 PIO_STACK_LOCATION Stack
;
721 PDEVICE_EXTENSION DeviceExt
;
722 PFILE_OBJECT FileObject
;
727 PDEVICE_OBJECT DeviceObject
;
728 NTSTATUS Status
= STATUS_NOT_IMPLEMENTED
;
730 DPRINT1("NtfsSetInformation(%p)\n", IrpContext
);
732 Irp
= IrpContext
->Irp
;
733 Stack
= IrpContext
->Stack
;
734 DeviceObject
= IrpContext
->DeviceObject
;
735 DeviceExt
= DeviceObject
->DeviceExtension
;
736 FileInformationClass
= Stack
->Parameters
.QueryFile
.FileInformationClass
;
737 FileObject
= IrpContext
->FileObject
;
738 Fcb
= FileObject
->FsContext
;
740 SystemBuffer
= Irp
->AssociatedIrp
.SystemBuffer
;
741 BufferLength
= Stack
->Parameters
.QueryFile
.Length
;
743 if (!ExAcquireResourceSharedLite(&Fcb
->MainResource
,
744 BooleanFlagOn(IrpContext
->Flags
, IRPCONTEXT_CANWAIT
)))
746 return NtfsMarkIrpContextForQueue(IrpContext
);
749 switch (FileInformationClass
)
751 PFILE_END_OF_FILE_INFORMATION EndOfFileInfo
;
753 /* TODO: Allocation size is not actually the same as file end for NTFS,
754 however, few applications are likely to make the distinction. */
755 case FileAllocationInformation
:
756 DPRINT1("FIXME: Using hacky method of setting FileAllocationInformation.\n");
757 case FileEndOfFileInformation
:
758 EndOfFileInfo
= (PFILE_END_OF_FILE_INFORMATION
)SystemBuffer
;
759 Status
= NtfsSetEndOfFile(Fcb
,
763 BooleanFlagOn(Stack
->Flags
, SL_CASE_SENSITIVE
),
764 &EndOfFileInfo
->EndOfFile
);
767 // TODO: all other information classes
770 DPRINT1("FIXME: Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass
));
771 Status
= STATUS_NOT_IMPLEMENTED
;
774 ExReleaseResourceLite(&Fcb
->MainResource
);
776 if (NT_SUCCESS(Status
))
777 Irp
->IoStatus
.Information
=
778 Stack
->Parameters
.QueryFile
.Length
- BufferLength
;
780 Irp
->IoStatus
.Information
= 0;