2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
11 /* INCLUDES *****************************************************************/
15 /* GLOBALS ***************************************************************/
17 extern PRFSD_GLOBAL RfsdGlobal
;
19 /* DEFINITIONS *************************************************************/
22 #pragma alloc_text(PAGE, RfsdQueryInformation)
23 #pragma alloc_text(PAGE, RfsdSetInformation)
25 #pragma alloc_text(PAGE, RfsdExpandFile)
26 #pragma alloc_text(PAGE, RfsdTruncateFile)
27 #pragma alloc_text(PAGE, RfsdSetDispositionInfo)
28 #pragma alloc_text(PAGE, RfsdSetRenameInfo)
29 #pragma alloc_text(PAGE, RfsdDeleteFile)
30 #endif // !RFSD_READ_ONLY
33 __drv_mustHoldCriticalRegion
35 RfsdQueryInformation (IN PRFSD_IRP_CONTEXT IrpContext
)
37 PDEVICE_OBJECT DeviceObject
;
38 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
39 PFILE_OBJECT FileObject
;
44 PIO_STACK_LOCATION IoStackLocation
;
45 FILE_INFORMATION_CLASS FileInformationClass
;
48 BOOLEAN FcbResourceAcquired
= FALSE
;
50 LONGLONG AllocationSize
;
56 ASSERT(IrpContext
!= NULL
);
58 ASSERT((IrpContext
->Identifier
.Type
== RFSDICX
) &&
59 (IrpContext
->Identifier
.Size
== sizeof(RFSD_IRP_CONTEXT
)));
61 DeviceObject
= IrpContext
->DeviceObject
;
64 // This request is not allowed on the main device object
66 if (DeviceObject
== RfsdGlobal
->DeviceObject
) {
67 Status
= STATUS_INVALID_DEVICE_REQUEST
;
71 FileObject
= IrpContext
->FileObject
;
73 Fcb
= (PRFSD_FCB
) FileObject
->FsContext
;
78 // This request is not allowed on volumes
80 if (Fcb
->Identifier
.Type
== RFSDVCB
) {
81 Status
= STATUS_INVALID_PARAMETER
;
85 ASSERT((Fcb
->Identifier
.Type
== RFSDFCB
) &&
86 (Fcb
->Identifier
.Size
== sizeof(RFSD_FCB
)));
91 if ( !IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
92 !FlagOn(Fcb->Flags, FCB_PAGE_FILE))
95 if (!ExAcquireResourceSharedLite(
97 IrpContext
->IsSynchronous
100 Status
= STATUS_PENDING
;
104 FcbResourceAcquired
= TRUE
;
107 Ccb
= (PRFSD_CCB
) FileObject
->FsContext2
;
111 ASSERT((Ccb
->Identifier
.Type
== RFSDCCB
) &&
112 (Ccb
->Identifier
.Size
== sizeof(RFSD_CCB
)));
114 Irp
= IrpContext
->Irp
;
116 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
118 FileInformationClass
=
119 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
;
121 Length
= IoStackLocation
->Parameters
.QueryFile
.Length
;
123 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
125 RtlZeroMemory(Buffer
, Length
);
127 FileSize
= (LONGLONG
) Fcb
->Inode
->i_size
;
129 AllocationSize
= CEILING_ALIGNED(FileSize
, (ULONGLONG
)Vcb
->BlockSize
);
131 switch (FileInformationClass
) {
133 case FileBasicInformation
:
135 PFILE_BASIC_INFORMATION FileBasicInformation
;
137 if (Length
< sizeof(FILE_BASIC_INFORMATION
)) {
138 Status
= STATUS_INFO_LENGTH_MISMATCH
;
142 FileBasicInformation
= (PFILE_BASIC_INFORMATION
) Buffer
;
144 FileBasicInformation
->CreationTime
= RfsdSysTime(Fcb
->Inode
->i_ctime
);
146 FileBasicInformation
->LastAccessTime
= RfsdSysTime(Fcb
->Inode
->i_atime
);
148 FileBasicInformation
->LastWriteTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
150 FileBasicInformation
->ChangeTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
152 FileBasicInformation
->FileAttributes
= Fcb
->RfsdMcb
->FileAttr
;
154 Irp
->IoStatus
.Information
= sizeof(FILE_BASIC_INFORMATION
);
155 Status
= STATUS_SUCCESS
;
159 #if (_WIN32_WINNT >= 0x0500)
161 case FileAttributeTagInformation
:
163 PFILE_ATTRIBUTE_TAG_INFORMATION FATI
;
165 if (Length
< sizeof(FILE_ATTRIBUTE_TAG_INFORMATION
)) {
166 Status
= STATUS_INFO_LENGTH_MISMATCH
;
170 FATI
= (PFILE_ATTRIBUTE_TAG_INFORMATION
) Buffer
;
172 FATI
->FileAttributes
= Fcb
->RfsdMcb
->FileAttr
;
173 FATI
->ReparseTag
= 0;
175 Irp
->IoStatus
.Information
= sizeof(FILE_ATTRIBUTE_TAG_INFORMATION
);
176 Status
= STATUS_SUCCESS
;
179 #endif // (_WIN32_WINNT >= 0x0500)
181 case FileStandardInformation
:
183 PFILE_STANDARD_INFORMATION FileStandardInformation
;
185 if (Length
< sizeof(FILE_STANDARD_INFORMATION
)) {
186 Status
= STATUS_INFO_LENGTH_MISMATCH
;
190 FileStandardInformation
= (PFILE_STANDARD_INFORMATION
) Buffer
;
192 FileStandardInformation
->AllocationSize
.QuadPart
= AllocationSize
;
193 FileStandardInformation
->EndOfFile
.QuadPart
= FileSize
;
195 FileStandardInformation
->NumberOfLinks
= Fcb
->Inode
->i_links_count
;
197 if (IsFlagOn(Fcb
->Vcb
->Flags
, VCB_READ_ONLY
))
198 FileStandardInformation
->DeletePending
= FALSE
;
200 FileStandardInformation
->DeletePending
= IsFlagOn(Fcb
->Flags
, FCB_DELETE_PENDING
);
202 if (Fcb
->RfsdMcb
->FileAttr
& FILE_ATTRIBUTE_DIRECTORY
) {
203 FileStandardInformation
->Directory
= TRUE
;
205 FileStandardInformation
->Directory
= FALSE
;
208 Irp
->IoStatus
.Information
= sizeof(FILE_STANDARD_INFORMATION
);
209 Status
= STATUS_SUCCESS
;
213 case FileInternalInformation
:
215 PFILE_INTERNAL_INFORMATION FileInternalInformation
;
217 if (Length
< sizeof(FILE_INTERNAL_INFORMATION
)) {
218 Status
= STATUS_INFO_LENGTH_MISMATCH
;
222 FileInternalInformation
= (PFILE_INTERNAL_INFORMATION
) Buffer
;
224 // The "inode number"
225 FileInternalInformation
->IndexNumber
.LowPart
= Fcb
->RfsdMcb
->Key
.k_dir_id
;
226 FileInternalInformation
->IndexNumber
.HighPart
= Fcb
->RfsdMcb
->Key
.k_objectid
;
228 Irp
->IoStatus
.Information
= sizeof(FILE_INTERNAL_INFORMATION
);
229 Status
= STATUS_SUCCESS
;
233 case FileEaInformation
:
235 PFILE_EA_INFORMATION FileEaInformation
;
237 if (Length
< sizeof(FILE_EA_INFORMATION
)) {
238 Status
= STATUS_INFO_LENGTH_MISMATCH
;
242 FileEaInformation
= (PFILE_EA_INFORMATION
) Buffer
;
244 // Romfs doesn't have any extended attributes
245 FileEaInformation
->EaSize
= 0;
247 Irp
->IoStatus
.Information
= sizeof(FILE_EA_INFORMATION
);
248 Status
= STATUS_SUCCESS
;
252 case FileNameInformation
:
254 PFILE_NAME_INFORMATION FileNameInformation
;
256 if (Length
< sizeof(FILE_NAME_INFORMATION
) +
257 Fcb
->RfsdMcb
->ShortName
.Length
- sizeof(WCHAR
)) {
258 Status
= STATUS_INFO_LENGTH_MISMATCH
;
262 FileNameInformation
= (PFILE_NAME_INFORMATION
) Buffer
;
264 FileNameInformation
->FileNameLength
= Fcb
->RfsdMcb
->ShortName
.Length
;
267 FileNameInformation
->FileName
,
268 Fcb
->RfsdMcb
->ShortName
.Buffer
,
269 Fcb
->RfsdMcb
->ShortName
.Length
);
271 Irp
->IoStatus
.Information
= sizeof(FILE_NAME_INFORMATION
) +
272 Fcb
->RfsdMcb
->ShortName
.Length
- sizeof(WCHAR
);
273 Status
= STATUS_SUCCESS
;
277 case FilePositionInformation
:
279 PFILE_POSITION_INFORMATION FilePositionInformation
;
281 if (Length
< sizeof(FILE_POSITION_INFORMATION
)) {
282 Status
= STATUS_INFO_LENGTH_MISMATCH
;
286 FilePositionInformation
= (PFILE_POSITION_INFORMATION
) Buffer
;
288 FilePositionInformation
->CurrentByteOffset
=
289 FileObject
->CurrentByteOffset
;
291 Irp
->IoStatus
.Information
= sizeof(FILE_POSITION_INFORMATION
);
292 Status
= STATUS_SUCCESS
;
296 case FileAllInformation
:
298 PFILE_ALL_INFORMATION FileAllInformation
;
299 PFILE_BASIC_INFORMATION FileBasicInformation
;
300 PFILE_STANDARD_INFORMATION FileStandardInformation
;
301 PFILE_INTERNAL_INFORMATION FileInternalInformation
;
302 PFILE_EA_INFORMATION FileEaInformation
;
303 PFILE_POSITION_INFORMATION FilePositionInformation
;
304 PFILE_NAME_INFORMATION FileNameInformation
;
306 if (Length
< sizeof(FILE_ALL_INFORMATION
)) {
307 Status
= STATUS_INFO_LENGTH_MISMATCH
;
311 FileAllInformation
= (PFILE_ALL_INFORMATION
) Buffer
;
313 FileBasicInformation
=
314 &FileAllInformation
->BasicInformation
;
316 FileStandardInformation
=
317 &FileAllInformation
->StandardInformation
;
319 FileInternalInformation
=
320 &FileAllInformation
->InternalInformation
;
323 &FileAllInformation
->EaInformation
;
325 FilePositionInformation
=
326 &FileAllInformation
->PositionInformation
;
328 FileNameInformation
=
329 &FileAllInformation
->NameInformation
;
331 FileBasicInformation
->CreationTime
= RfsdSysTime(Fcb
->Inode
->i_ctime
);
333 FileBasicInformation
->LastAccessTime
= RfsdSysTime(Fcb
->Inode
->i_atime
);
335 FileBasicInformation
->LastWriteTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
337 FileBasicInformation
->ChangeTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
339 FileBasicInformation
->FileAttributes
= Fcb
->RfsdMcb
->FileAttr
;
341 FileStandardInformation
->AllocationSize
.QuadPart
= AllocationSize
;
343 FileStandardInformation
->EndOfFile
.QuadPart
= FileSize
;
345 FileStandardInformation
->NumberOfLinks
= Fcb
->Inode
->i_links_count
;
347 if (IsFlagOn(Fcb
->Vcb
->Flags
, VCB_READ_ONLY
))
348 FileStandardInformation
->DeletePending
= FALSE
;
350 FileStandardInformation
->DeletePending
= IsFlagOn(Fcb
->Flags
, FCB_DELETE_PENDING
);
352 if (FlagOn(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
)) {
353 FileStandardInformation
->Directory
= TRUE
;
355 FileStandardInformation
->Directory
= FALSE
;
358 // The "inode number"
359 FileInternalInformation
->IndexNumber
.LowPart
= Fcb
->RfsdMcb
->Key
.k_dir_id
;
360 FileInternalInformation
->IndexNumber
.HighPart
= Fcb
->RfsdMcb
->Key
.k_objectid
;
362 // Romfs doesn't have any extended attributes
363 FileEaInformation
->EaSize
= 0;
365 FilePositionInformation
->CurrentByteOffset
=
366 FileObject
->CurrentByteOffset
;
368 if (Length
< sizeof(FILE_ALL_INFORMATION
) +
369 Fcb
->RfsdMcb
->ShortName
.Length
- sizeof(WCHAR
)) {
370 Irp
->IoStatus
.Information
= sizeof(FILE_ALL_INFORMATION
);
371 Status
= STATUS_BUFFER_OVERFLOW
;
375 FileNameInformation
->FileNameLength
= Fcb
->RfsdMcb
->ShortName
.Length
;
378 FileNameInformation
->FileName
,
379 Fcb
->RfsdMcb
->ShortName
.Buffer
,
380 Fcb
->RfsdMcb
->ShortName
.Length
383 Irp
->IoStatus
.Information
= sizeof(FILE_ALL_INFORMATION
) +
384 Fcb
->RfsdMcb
->ShortName
.Length
- sizeof(WCHAR
);
385 Status
= STATUS_SUCCESS
;
390 case FileAlternateNameInformation:
392 // TODO: [ext2fsd] Handle FileAlternateNameInformation
394 // Here we would like to use RtlGenerate8dot3Name but I don't
395 // know how to use the argument PGENERATE_NAME_CONTEXT
399 case FileNetworkOpenInformation
:
401 PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation
;
403 if (Length
< sizeof(FILE_NETWORK_OPEN_INFORMATION
)) {
404 Status
= STATUS_INFO_LENGTH_MISMATCH
;
408 FileNetworkOpenInformation
=
409 (PFILE_NETWORK_OPEN_INFORMATION
) Buffer
;
411 FileNetworkOpenInformation
->CreationTime
= RfsdSysTime(Fcb
->Inode
->i_ctime
);
413 FileNetworkOpenInformation
->LastAccessTime
= RfsdSysTime(Fcb
->Inode
->i_atime
);
415 FileNetworkOpenInformation
->LastWriteTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
417 FileNetworkOpenInformation
->ChangeTime
= RfsdSysTime(Fcb
->Inode
->i_mtime
);
419 FileNetworkOpenInformation
->AllocationSize
.QuadPart
= AllocationSize
;
421 FileNetworkOpenInformation
->EndOfFile
.QuadPart
= FileSize
;
423 FileNetworkOpenInformation
->FileAttributes
= Fcb
->RfsdMcb
->FileAttr
;
425 Irp
->IoStatus
.Information
=
426 sizeof(FILE_NETWORK_OPEN_INFORMATION
);
427 Status
= STATUS_SUCCESS
;
432 Status
= STATUS_INVALID_INFO_CLASS
;
437 if (FcbResourceAcquired
) {
438 ExReleaseResourceForThreadLite(
440 ExGetCurrentResourceThread());
443 if (!IrpContext
->ExceptionInProgress
) {
444 if (Status
== STATUS_PENDING
) {
445 RfsdQueueRequest(IrpContext
);
447 RfsdCompleteIrpContext(IrpContext
, Status
);
455 __drv_mustHoldCriticalRegion
457 RfsdSetInformation (IN PRFSD_IRP_CONTEXT IrpContext
)
459 PDEVICE_OBJECT DeviceObject
;
460 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
462 PFILE_OBJECT FileObject
;
466 PIO_STACK_LOCATION IoStackLocation
;
467 FILE_INFORMATION_CLASS FileInformationClass
;
469 ULONG NotifyFilter
= 0;
473 BOOLEAN FcbMainResourceAcquired
= FALSE
;
475 BOOLEAN VcbResourceAcquired
= FALSE
;
476 BOOLEAN FcbPagingIoResourceAcquired
= FALSE
;
482 ASSERT(IrpContext
!= NULL
);
484 ASSERT((IrpContext
->Identifier
.Type
== RFSDICX
) &&
485 (IrpContext
->Identifier
.Size
== sizeof(RFSD_IRP_CONTEXT
)));
487 DeviceObject
= IrpContext
->DeviceObject
;
490 // This request is not allowed on the main device object
492 if (DeviceObject
== RfsdGlobal
->DeviceObject
) {
493 Status
= STATUS_INVALID_DEVICE_REQUEST
;
497 Vcb
= (PRFSD_VCB
) DeviceObject
->DeviceExtension
;
501 ASSERT((Vcb
->Identifier
.Type
== RFSDVCB
) &&
502 (Vcb
->Identifier
.Size
== sizeof(RFSD_VCB
)));
504 ASSERT(IsMounted(Vcb
));
506 FileObject
= IrpContext
->FileObject
;
508 Fcb
= (PRFSD_FCB
) FileObject
->FsContext
;
513 // This request is not allowed on volumes
515 if (Fcb
->Identifier
.Type
== RFSDVCB
) {
518 Status
= STATUS_INVALID_PARAMETER
;
522 ASSERT((Fcb
->Identifier
.Type
== RFSDFCB
) &&
523 (Fcb
->Identifier
.Size
== sizeof(RFSD_FCB
)));
525 if (IsFlagOn(Fcb
->Flags
, FCB_FILE_DELETED
)) {
526 Status
= STATUS_FILE_DELETED
;
530 Ccb
= (PRFSD_CCB
) FileObject
->FsContext2
;
534 ASSERT((Ccb
->Identifier
.Type
== RFSDCCB
) &&
535 (Ccb
->Identifier
.Size
== sizeof(RFSD_CCB
)));
537 Irp
= IrpContext
->Irp
;
539 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
541 FileInformationClass
=
542 IoStackLocation
->Parameters
.SetFile
.FileInformationClass
;
544 Length
= IoStackLocation
->Parameters
.SetFile
.Length
;
546 Buffer
= Irp
->AssociatedIrp
.SystemBuffer
;
548 if (IsFlagOn(Vcb
->Flags
, VCB_READ_ONLY
)) {
550 if (FileInformationClass
== FileDispositionInformation
||
551 FileInformationClass
== FileRenameInformation
||
552 FileInformationClass
== FileLinkInformation
) {
555 #pragma prefast( suppress: 28137, "by design" )
557 if (!ExAcquireResourceExclusiveLite(
559 IrpContext
->IsSynchronous
)) {
561 Status
= STATUS_PENDING
;
565 VcbResourceAcquired
= TRUE
;
568 } else if (!FlagOn(Fcb
->Flags
, FCB_PAGE_FILE
)) {
571 #pragma prefast( suppress: 28137, "by design" )
573 if (!ExAcquireResourceExclusiveLite(
575 IrpContext
->IsSynchronous
)) {
576 Status
= STATUS_PENDING
;
580 FcbMainResourceAcquired
= TRUE
;
583 if (IsFlagOn(Vcb
->Flags
, VCB_READ_ONLY
)) {
585 if (FileInformationClass
!= FilePositionInformation
) {
586 Status
= STATUS_MEDIA_WRITE_PROTECTED
;
591 if (FileInformationClass
== FileDispositionInformation
||
592 FileInformationClass
== FileRenameInformation
||
593 FileInformationClass
== FileLinkInformation
||
594 FileInformationClass
== FileAllocationInformation
||
595 FileInformationClass
== FileEndOfFileInformation
) {
598 #pragma prefast( suppress: 28137, "by design" )
600 if (!ExAcquireResourceExclusiveLite(
601 &Fcb
->PagingIoResource
,
602 IrpContext
->IsSynchronous
)) {
603 Status
= STATUS_PENDING
;
607 FcbPagingIoResourceAcquired
= TRUE
;
611 if (FileInformationClass != FileDispositionInformation
612 && FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
614 Status = STATUS_DELETE_PENDING;
618 switch (FileInformationClass
) {
622 case FileBasicInformation
:
624 PFILE_BASIC_INFORMATION FBI
= (PFILE_BASIC_INFORMATION
) Buffer
;
625 PRFSD_INODE RfsdInode
= Fcb
->Inode
;
627 if (FBI
->CreationTime
.QuadPart
) {
628 RfsdInode
->i_ctime
= (ULONG
)(RfsdInodeTime(FBI
->CreationTime
));
631 if (FBI
->LastAccessTime
.QuadPart
) {
632 RfsdInode
->i_atime
= (ULONG
)(RfsdInodeTime(FBI
->LastAccessTime
));
635 if (FBI
->LastWriteTime
.QuadPart
) {
636 RfsdInode
->i_mtime
= (ULONG
)(RfsdInodeTime(FBI
->LastWriteTime
));
639 if (IsFlagOn(FBI
->FileAttributes
, FILE_ATTRIBUTE_READONLY
)) {
640 RfsdSetReadOnly(Fcb
->Inode
->i_mode
);
641 SetFlag(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_READONLY
);
643 RfsdSetWritable(Fcb
->Inode
->i_mode
);
644 ClearFlag(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_READONLY
);
647 if(RfsdSaveInode(IrpContext
, Vcb
, Fcb
->RfsdMcb
->Inode
, RfsdInode
)) {
648 Status
= STATUS_SUCCESS
;
651 if (FBI
->FileAttributes
& FILE_ATTRIBUTE_TEMPORARY
) {
652 SetFlag(FileObject
->Flags
, FO_TEMPORARY_FILE
);
654 ClearFlag(FileObject
->Flags
, FO_TEMPORARY_FILE
);
657 NotifyFilter
= FILE_NOTIFY_CHANGE_ATTRIBUTES
|
658 FILE_NOTIFY_CHANGE_CREATION
|
659 FILE_NOTIFY_CHANGE_LAST_ACCESS
|
660 FILE_NOTIFY_CHANGE_LAST_WRITE
;
662 Status
= STATUS_SUCCESS
;
667 case FileAllocationInformation
:
669 PFILE_ALLOCATION_INFORMATION FAI
= (PFILE_ALLOCATION_INFORMATION
)Buffer
;
671 if (FlagOn(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
)) {
672 Status
= STATUS_INVALID_DEVICE_REQUEST
;
676 if ( FAI
->AllocationSize
.QuadPart
==
677 Fcb
->Header
.AllocationSize
.QuadPart
) {
679 Status
= STATUS_SUCCESS
;
681 } else if ( FAI
->AllocationSize
.QuadPart
>
682 Fcb
->Header
.AllocationSize
.QuadPart
) {
684 Status
= RfsdExpandFile(
687 &(FAI
->AllocationSize
));
689 if (NT_SUCCESS(Status
)) {
691 RfsdSaveInode( IrpContext
,
699 if (MmCanFileBeTruncated(&(Fcb
->SectionObject
), &(FAI
->AllocationSize
))) {
701 LARGE_INTEGER EndOfFile
;
703 EndOfFile
.QuadPart
= FAI
->AllocationSize
.QuadPart
+
704 (LONGLONG
)(Vcb
->BlockSize
- 1);
706 Status
= RfsdTruncateFile(IrpContext
, Vcb
, Fcb
, &(EndOfFile
));
708 if (NT_SUCCESS(Status
)) {
710 if ( FAI
->AllocationSize
.QuadPart
<
711 Fcb
->Header
.FileSize
.QuadPart
) {
712 Fcb
->Header
.FileSize
.QuadPart
=
713 FAI
->AllocationSize
.QuadPart
;
716 RfsdSaveInode( IrpContext
,
724 Status
= STATUS_USER_MAPPED_FILE
;
729 if (NT_SUCCESS(Status
)) {
731 CcSetFileSizes(FileObject
,
732 (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
733 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
735 NotifyFilter
= FILE_NOTIFY_CHANGE_SIZE
|
736 FILE_NOTIFY_CHANGE_LAST_WRITE
;
744 case FileEndOfFileInformation
:
746 PFILE_END_OF_FILE_INFORMATION FEOFI
= (PFILE_END_OF_FILE_INFORMATION
) Buffer
;
748 BOOLEAN CacheInitialized
= FALSE
;
750 if (IsDirectory(Fcb
)) {
751 Status
= STATUS_INVALID_DEVICE_REQUEST
;
755 if (FEOFI
->EndOfFile
.HighPart
!= 0) {
756 Status
= STATUS_INVALID_PARAMETER
;
761 if (IoStackLocation
->Parameters
.SetFile
.AdvanceOnly
) {
762 Status
= STATUS_SUCCESS
;
766 if ((FileObject
->SectionObjectPointer
->DataSectionObject
!= NULL
) &&
767 (FileObject
->SectionObjectPointer
->SharedCacheMap
== NULL
) &&
768 !FlagOn(Irp
->Flags
, IRP_PAGING_IO
)) {
770 ASSERT( !FlagOn( FileObject
->Flags
, FO_CLEANUP_COMPLETE
) );
772 CcInitializeCacheMap(
774 (PCC_FILE_SIZES
)&(Fcb
->Header
.AllocationSize
),
776 &(RfsdGlobal
->CacheManagerNoOpCallbacks
),
779 CacheInitialized
= TRUE
;
782 if ( FEOFI
->EndOfFile
.QuadPart
==
783 Fcb
->Header
.AllocationSize
.QuadPart
) {
785 Status
= STATUS_SUCCESS
;
787 } else if ( FEOFI
->EndOfFile
.QuadPart
>
788 Fcb
->Header
.AllocationSize
.QuadPart
) {
790 LARGE_INTEGER FileSize
= Fcb
->Header
.FileSize
;
792 Status
= RfsdExpandFile(IrpContext
, Vcb
, Fcb
, &(FEOFI
->EndOfFile
));
794 if (NT_SUCCESS(Status
)) {
796 Fcb
->Header
.FileSize
.QuadPart
= FEOFI
->EndOfFile
.QuadPart
;
798 Fcb
->Inode
->i_size
= FEOFI
->EndOfFile
.QuadPart
;
800 Fcb
->Header
.ValidDataLength
.QuadPart
=
801 (LONGLONG
)(0x7fffffffffffffff);
803 RfsdSaveInode( IrpContext
,
809 CcSetFileSizes(FileObject
,
810 (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
812 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
814 RfsdZeroHoles( IrpContext
,
817 Fcb
->Header
.AllocationSize
.QuadPart
-
820 NotifyFilter
= FILE_NOTIFY_CHANGE_SIZE
|
821 FILE_NOTIFY_CHANGE_LAST_WRITE
;
826 if (MmCanFileBeTruncated(&(Fcb
->SectionObject
), &(FEOFI
->EndOfFile
))) {
828 LARGE_INTEGER EndOfFile
= FEOFI
->EndOfFile
;
830 EndOfFile
.QuadPart
= EndOfFile
.QuadPart
+
831 (LONGLONG
)(Vcb
->BlockSize
- 1);
833 Status
= RfsdTruncateFile(IrpContext
, Vcb
, Fcb
, &(EndOfFile
));
835 if (NT_SUCCESS(Status
)) {
837 Fcb
->Header
.FileSize
.QuadPart
= FEOFI
->EndOfFile
.QuadPart
;
838 Fcb
->Inode
->i_size
= FEOFI
->EndOfFile
.QuadPart
;
840 RfsdSaveInode( IrpContext
,
845 CcSetFileSizes(FileObject
,
846 (PCC_FILE_SIZES
)(&(Fcb
->Header
.AllocationSize
)));
848 SetFlag(FileObject
->Flags
, FO_FILE_MODIFIED
);
850 NotifyFilter
= FILE_NOTIFY_CHANGE_SIZE
|
851 FILE_NOTIFY_CHANGE_LAST_WRITE
;
856 Status
= STATUS_USER_MAPPED_FILE
;
864 case FileDispositionInformation
:
866 PFILE_DISPOSITION_INFORMATION FDI
= (PFILE_DISPOSITION_INFORMATION
)Buffer
;
868 Status
= RfsdSetDispositionInfo(IrpContext
, Vcb
, Fcb
, FDI
->DeleteFile
);
873 case FileRenameInformation
:
875 Status
= RfsdSetRenameInfo(IrpContext
, Vcb
, Fcb
);
880 #endif // !RFSD_READ_ONLY
883 // This is the only set file information request supported on read
886 case FilePositionInformation
:
888 PFILE_POSITION_INFORMATION FilePositionInformation
;
890 if (Length
< sizeof(FILE_POSITION_INFORMATION
)) {
891 Status
= STATUS_INVALID_PARAMETER
;
895 FilePositionInformation
= (PFILE_POSITION_INFORMATION
) Buffer
;
897 if ((FlagOn(FileObject
->Flags
, FO_NO_INTERMEDIATE_BUFFERING
)) &&
898 (FilePositionInformation
->CurrentByteOffset
.LowPart
&
899 DeviceObject
->AlignmentRequirement
) ) {
900 Status
= STATUS_INVALID_PARAMETER
;
904 FileObject
->CurrentByteOffset
=
905 FilePositionInformation
->CurrentByteOffset
;
907 Status
= STATUS_SUCCESS
;
914 Status
= STATUS_INVALID_INFO_CLASS
;
919 if (FcbPagingIoResourceAcquired
) {
920 ExReleaseResourceForThreadLite(
921 &Fcb
->PagingIoResource
,
922 ExGetCurrentResourceThread() );
925 if (NT_SUCCESS(Status
) && (NotifyFilter
!= 0)) {
926 RfsdNotifyReportChange(
931 FILE_ACTION_MODIFIED
);
935 if (FcbMainResourceAcquired
) {
936 ExReleaseResourceForThreadLite(
938 ExGetCurrentResourceThread() );
941 if (VcbResourceAcquired
) {
942 ExReleaseResourceForThreadLite(
944 ExGetCurrentResourceThread() );
947 if (!IrpContext
->ExceptionInProgress
) {
948 if (Status
== STATUS_PENDING
) {
949 RfsdQueueRequest(IrpContext
);
951 RfsdCompleteIrpContext(IrpContext
, Status
);
962 RfsdExpandFile( PRFSD_IRP_CONTEXT IrpContext
,
963 PRFSD_VCB Vcb
, PRFSD_FCB Fcb
,
964 PLARGE_INTEGER AllocationSize
)
967 NTSTATUS Status
= STATUS_SUCCESS
;
971 if (AllocationSize
->QuadPart
<= Fcb
->Header
.AllocationSize
.QuadPart
) {
975 if (((LONGLONG
)SUPER_BLOCK
->s_free_blocks_count
) * Vcb
->BlockSize
<=
976 (AllocationSize
->QuadPart
- Fcb
->Header
.AllocationSize
.QuadPart
) ) {
977 RfsdPrint((DBG_ERROR
, "RfsdExpandFile: There is no enough disk space available.\n"));
978 return STATUS_DISK_FULL
;
981 while (NT_SUCCESS(Status
) && (AllocationSize
->QuadPart
> Fcb
->Header
.AllocationSize
.QuadPart
)) {
982 Status
= RfsdExpandInode(IrpContext
, Vcb
, Fcb
, &dwRet
);
989 RfsdTruncateFile( PRFSD_IRP_CONTEXT IrpContext
,
990 PRFSD_VCB Vcb
, PRFSD_FCB Fcb
,
991 PLARGE_INTEGER AllocationSize
)
993 NTSTATUS Status
= STATUS_SUCCESS
;
997 while (NT_SUCCESS(Status
) && (AllocationSize
->QuadPart
<
998 Fcb
->Header
.AllocationSize
.QuadPart
)) {
999 Status
= RfsdTruncateInode(IrpContext
, Vcb
, Fcb
);
1006 RfsdSetDispositionInfo(
1007 PRFSD_IRP_CONTEXT IrpContext
,
1012 PIRP Irp
= IrpContext
->Irp
;
1013 PIO_STACK_LOCATION IrpSp
;
1017 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1019 RfsdPrint((DBG_INFO
, "RfsdSetDispositionInfo: bDelete=%x\n", bDelete
));
1023 RfsdPrint((DBG_INFO
, "RfsdSetDispositionInformation: MmFlushImageSection on %s.\n",
1024 Fcb
->AnsiFileName
.Buffer
));
1026 if (!MmFlushImageSection( &Fcb
->SectionObject
,
1027 MmFlushForDelete
)) {
1028 return STATUS_CANNOT_DELETE
;
1031 if (RFSD_IS_ROOT_KEY(Fcb
->RfsdMcb
->Key
)) {
1032 return STATUS_CANNOT_DELETE
;
1035 if (IsDirectory(Fcb
)) {
1036 if (!RfsdIsDirectoryEmpty(Vcb
, Fcb
)) {
1037 return STATUS_DIRECTORY_NOT_EMPTY
;
1041 SetFlag(Fcb
->Flags
, FCB_DELETE_PENDING
);
1042 IrpSp
->FileObject
->DeletePending
= TRUE
;
1044 if (IsDirectory(Fcb
)) {
1045 FsRtlNotifyFullChangeDirectory( Vcb
->NotifySync
,
1059 ClearFlag(Fcb
->Flags
, FCB_DELETE_PENDING
);
1060 IrpSp
->FileObject
->DeletePending
= FALSE
;
1063 return STATUS_SUCCESS
;
1068 PRFSD_IRP_CONTEXT IrpContext
,
1072 PRFSD_FCB TargetDcb
;
1073 PRFSD_MCB TargetMcb
;
1078 UNICODE_STRING FileName
;
1083 PIO_STACK_LOCATION IrpSp
;
1085 PFILE_OBJECT FileObject
;
1086 PFILE_OBJECT TargetObject
;
1087 BOOLEAN ReplaceIfExists
;
1089 BOOLEAN bMove
= FALSE
;
1091 PFILE_RENAME_INFORMATION FRI
;
1095 if (Fcb
->RfsdMcb
->Inode
== RFSD_ROOT_INO
) {
1096 Status
= STATUS_INVALID_PARAMETER
;
1100 Irp
= IrpContext
->Irp
;
1101 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1103 FileObject
= IrpSp
->FileObject
;
1104 TargetObject
= IrpSp
->Parameters
.SetFile
.FileObject
;
1105 ReplaceIfExists
= IrpSp
->Parameters
.SetFile
.ReplaceIfExists
;
1107 FRI
= (PFILE_RENAME_INFORMATION
)Irp
->AssociatedIrp
.SystemBuffer
;
1109 if (TargetObject
== NULL
) {
1111 UNICODE_STRING NewName
;
1113 NewName
.Buffer
= FRI
->FileName
;
1114 NewName
.MaximumLength
= NewName
.Length
= (USHORT
)FRI
->FileNameLength
;
1116 while (NewName
.Length
> 0 && NewName
.Buffer
[NewName
.Length
/2 - 1] == L
'\\') {
1117 NewName
.Buffer
[NewName
.Length
/2 - 1] = 0;
1118 NewName
.Length
-= 2;
1121 while (NewName
.Length
> 0 && NewName
.Buffer
[NewName
.Length
/2 - 1] != L
'\\') {
1122 NewName
.Length
-= 2;
1125 NewName
.Buffer
= (USHORT
*)((UCHAR
*)NewName
.Buffer
+ NewName
.Length
);
1126 NewName
.Length
= (USHORT
)(FRI
->FileNameLength
- NewName
.Length
);
1131 TargetMcb
= Fcb
->RfsdMcb
->Parent
;
1133 if (FileName
.Length
>= RFSD_NAME_LEN
*sizeof(USHORT
)) {
1134 Status
= STATUS_OBJECT_NAME_INVALID
;
1140 TargetDcb
= (PRFSD_FCB
)(TargetObject
->FsContext
);
1142 if (!TargetDcb
|| TargetDcb
->Vcb
!= Vcb
) {
1146 Status
= STATUS_INVALID_PARAMETER
;
1150 TargetMcb
= TargetDcb
->RfsdMcb
;
1152 FileName
= TargetObject
->FileName
;
1155 if (FsRtlDoesNameContainWildCards(&FileName
)) {
1156 Status
= STATUS_OBJECT_NAME_INVALID
;
1160 if (TargetMcb
->Inode
== Fcb
->RfsdMcb
->Parent
->Inode
) {
1161 if (FsRtlAreNamesEqual( &FileName
,
1162 &(Fcb
->RfsdMcb
->ShortName
),
1165 Status
= STATUS_SUCCESS
;
1172 TargetDcb
= TargetMcb
->RfsdFcb
;
1175 TargetDcb
= RfsdCreateFcbFromMcb(Vcb
, TargetMcb
);
1177 if ((TargetMcb
->Inode
!= Fcb
->RfsdMcb
->Parent
->Inode
) &&
1178 (Fcb
->RfsdMcb
->Parent
->RfsdFcb
== NULL
) ) {
1179 RfsdCreateFcbFromMcb(Vcb
, Fcb
->RfsdMcb
->Parent
);
1182 if (!TargetDcb
|| !(Fcb
->RfsdMcb
->Parent
->RfsdFcb
)) {
1183 Status
= STATUS_UNSUCCESSFUL
;
1189 Status
= RfsdLookupFileName(
1196 if (NT_SUCCESS(Status
)) {
1198 if ( (!ReplaceIfExists
) ||
1199 (IsFlagOn(Mcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
)) ||
1200 (IsFlagOn(Mcb
->FileAttr
, FILE_ATTRIBUTE_READONLY
))) {
1201 Status
= STATUS_OBJECT_NAME_COLLISION
;
1205 if (ReplaceIfExists
) {
1206 Status
= STATUS_NOT_IMPLEMENTED
;
1211 if (IsDirectory(Fcb
)) {
1213 Status
= RfsdRemoveEntry( IrpContext
, Vcb
,
1214 Fcb
->RfsdMcb
->Parent
->RfsdFcb
,
1216 Fcb
->RfsdMcb
->Inode
);
1218 if (!NT_SUCCESS(Status
)) {
1224 Status
= RfsdAddEntry( IrpContext
, Vcb
,
1227 Fcb
->RfsdMcb
->Inode
,
1230 if (!NT_SUCCESS(Status
)) {
1234 RfsdAddEntry( IrpContext
, Vcb
,
1235 Fcb
->RfsdMcb
->Parent
->RfsdFcb
,
1237 Fcb
->RfsdMcb
->Inode
,
1238 &Fcb
->RfsdMcb
->ShortName
);
1243 if( !RfsdSaveInode( IrpContext
,
1246 TargetDcb
->Inode
)) {
1247 Status
= STATUS_UNSUCCESSFUL
;
1254 if( !RfsdSaveInode( IrpContext
,
1256 Fcb
->RfsdMcb
->Parent
->Inode
,
1257 Fcb
->RfsdMcb
->Parent
->RfsdFcb
->Inode
)) {
1259 Status
= STATUS_UNSUCCESSFUL
;
1266 Status
= RfsdSetParentEntry( IrpContext
, Vcb
, Fcb
,
1267 Fcb
->RfsdMcb
->Parent
->Inode
,
1268 TargetDcb
->RfsdMcb
->Inode
);
1271 if (!NT_SUCCESS(Status
)) {
1278 Status
= RfsdRemoveEntry( IrpContext
, Vcb
,
1279 Fcb
->RfsdMcb
->Parent
->RfsdFcb
,
1281 Fcb
->RfsdMcb
->Inode
);
1282 if (!NT_SUCCESS(Status
)) {
1287 Status
= RfsdAddEntry( IrpContext
,
1290 Fcb
->RfsdMcb
->Inode
,
1293 if (!NT_SUCCESS(Status
)) {
1297 RfsdAddEntry( IrpContext
, Vcb
,
1298 Fcb
->RfsdMcb
->Parent
->RfsdFcb
,
1300 Fcb
->RfsdMcb
->Inode
,
1301 &Fcb
->RfsdMcb
->ShortName
);
1307 if (NT_SUCCESS(Status
)) {
1309 if (Fcb
->RfsdMcb
->ShortName
.MaximumLength
< (FileName
.Length
+ 2)) {
1311 ExFreePool(Fcb
->RfsdMcb
->ShortName
.Buffer
);
1312 Fcb
->RfsdMcb
->ShortName
.Buffer
=
1313 ExAllocatePoolWithTag(PagedPool
, FileName
.Length
+ 2, RFSD_POOL_TAG
);
1315 if (!Fcb
->RfsdMcb
->ShortName
.Buffer
) {
1316 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1320 Fcb
->RfsdMcb
->ShortName
.MaximumLength
= FileName
.Length
+ 2;
1324 RtlZeroMemory( Fcb
->RfsdMcb
->ShortName
.Buffer
,
1325 Fcb
->RfsdMcb
->ShortName
.MaximumLength
);
1327 RtlCopyMemory( Fcb
->RfsdMcb
->ShortName
.Buffer
,
1328 FileName
.Buffer
, FileName
.Length
);
1330 Fcb
->RfsdMcb
->ShortName
.Length
= FileName
.Length
;
1335 Fcb
->AnsiFileName
.Length
= (USHORT
)
1336 RfsdUnicodeToOEMSize(&FileName
) + 1;
1338 if (Fcb
->AnsiFileName
.MaximumLength
< FileName
.Length
) {
1339 ExFreePool(Fcb
->AnsiFileName
.Buffer
);
1341 Fcb
->AnsiFileName
.Buffer
=
1342 ExAllocatePoolWithTag(PagedPool
, Fcb
->AnsiFileName
.Length
+ 1, RFSD_POOL_TAG
);
1344 if (!Fcb
->AnsiFileName
.Buffer
) {
1345 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1349 RtlZeroMemory( Fcb
->AnsiFileName
.Buffer
,
1350 Fcb
->AnsiFileName
.Length
+ 1);
1351 Fcb
->AnsiFileName
.MaximumLength
=
1352 Fcb
->AnsiFileName
.Length
+ 1;
1355 RfsdUnicodeToOEM( &(Fcb
->AnsiFileName
),
1362 RfsdNotifyReportChange(
1367 FILE_NOTIFY_CHANGE_DIR_NAME
:
1368 FILE_NOTIFY_CHANGE_FILE_NAME
),
1369 FILE_ACTION_REMOVED
);
1373 RfsdNotifyReportChange(
1378 FILE_NOTIFY_CHANGE_DIR_NAME
:
1379 FILE_NOTIFY_CHANGE_FILE_NAME
),
1380 FILE_ACTION_RENAMED_OLD_NAME
);
1384 RfsdDeleteMcbNode(Vcb
, Fcb
->RfsdMcb
->Parent
, Fcb
->RfsdMcb
);
1385 RfsdAddMcbNode(Vcb
, TargetMcb
, Fcb
->RfsdMcb
);
1389 RfsdNotifyReportChange(
1394 FILE_NOTIFY_CHANGE_DIR_NAME
:
1395 FILE_NOTIFY_CHANGE_FILE_NAME
),
1399 RfsdNotifyReportChange(
1404 FILE_NOTIFY_CHANGE_DIR_NAME
:
1405 FILE_NOTIFY_CHANGE_FILE_NAME
),
1406 FILE_ACTION_RENAMED_NEW_NAME
);
1418 PRFSD_IRP_CONTEXT IrpContext
,
1422 BOOLEAN bRet
= FALSE
;
1423 LARGE_INTEGER AllocationSize
;
1424 PRFSD_FCB Dcb
= NULL
;
1425 NTSTATUS Status
= STATUS_SUCCESS
;
1429 RfsdPrint((DBG_INFO
, "RfsdDeleteFile: File %S (%xh) will be deleted!\n",
1430 Fcb
->RfsdMcb
->ShortName
.Buffer
, Fcb
->RfsdMcb
->Inode
));
1432 if (IsFlagOn(Fcb
->Flags
, FCB_FILE_DELETED
)) {
1436 if (FlagOn(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
)) {
1437 if (!RfsdIsDirectoryEmpty(Vcb
, Fcb
)) {
1438 ClearFlag(Fcb
->Flags
, FCB_DELETE_PENDING
);
1440 return STATUS_DIRECTORY_NOT_EMPTY
;
1444 RfsdPrint((DBG_INFO
, "RfsdDeleteFile: RFSDSB->S_FREE_BLOCKS = %xh .\n",
1445 Vcb
->SuperBlock
->s_free_blocks_count
));
1447 if (IsDirectory(Fcb
)) {
1448 if (Fcb
->Inode
->i_links_count
<= 2) {
1450 Status
= STATUS_CANNOT_DELETE
;
1453 if (Fcb
->Inode
->i_links_count
<= 1) {
1455 Status
= STATUS_CANNOT_DELETE
;
1459 if (!NT_SUCCESS(Status
)) {
1464 if (Fcb
->RfsdMcb
->Parent
->RfsdFcb
) {
1466 Status
= RfsdRemoveEntry(
1468 Fcb
->RfsdMcb
->Parent
->RfsdFcb
,
1469 (FlagOn(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
) ?
1470 RFSD_FT_DIR
: RFSD_FT_REG_FILE
),
1471 Fcb
->RfsdMcb
->Inode
);
1474 Dcb
= RfsdCreateFcbFromMcb(Vcb
, Fcb
->RfsdMcb
->Parent
);
1476 Status
= RfsdRemoveEntry(
1477 IrpContext
, Vcb
, Dcb
,
1478 (FlagOn(Fcb
->RfsdMcb
->FileAttr
, FILE_ATTRIBUTE_DIRECTORY
) ?
1479 RFSD_FT_DIR
: RFSD_FT_REG_FILE
),
1480 Fcb
->RfsdMcb
->Inode
);
1484 if (NT_SUCCESS(Status
)) {
1486 LARGE_INTEGER SysTime
;
1487 KeQuerySystemTime(&SysTime
);
1489 AllocationSize
.QuadPart
= (LONGLONG
)0;
1491 Status
= RfsdTruncateFile(IrpContext
, Vcb
, Fcb
, &AllocationSize
);
1494 // Update the inode's data length . It should be ZERO if succeeds.
1497 if (Fcb
->Header
.FileSize
.QuadPart
> Fcb
->Header
.AllocationSize
.QuadPart
) {
1499 Fcb
->Header
.FileSize
.QuadPart
= Fcb
->Header
.AllocationSize
.QuadPart
;
1500 Fcb
->Inode
->i_size
= Fcb
->Header
.AllocationSize
.QuadPart
;
1503 Fcb
->Inode
->i_links_count
= 0;
1505 RfsdSaveInode(IrpContext
, Vcb
, Fcb
->RfsdMcb
->Inode
, Fcb
->Inode
);
1507 if (IsDirectory(Fcb
)) {
1508 bRet
= RfsdFreeInode(IrpContext
, Vcb
, Fcb
->RfsdMcb
->Inode
, RFSD_FT_DIR
);
1510 bRet
= RfsdFreeInode(IrpContext
, Vcb
, Fcb
->RfsdMcb
->Inode
, RFSD_FT_REG_FILE
);
1513 SetFlag(Fcb
->Flags
, FCB_FILE_DELETED
);
1514 RfsdDeleteMcbNode(Vcb
, Fcb
->RfsdMcb
->Parent
, Fcb
->RfsdMcb
);
1518 RfsdSaveInode(IrpContext
, Vcb
, Fcb
->RfsdMcb
->Inode
, Fcb
->Inode
);
1521 RfsdPrint((DBG_INFO
, "RfsdDeleteFile: Succeed... RFSDSB->S_FREE_BLOCKS = %xh .\n",
1522 Vcb
->SuperBlock
->s_free_blocks_count
));
1527 #endif // !RFSD_READ_ONLY