⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileinfo.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 3 页
字号:

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		ASSERT(IsMounted(Vcb));

		FileObject = IrpContext->FileObject;

		Fcb = (PFFS_FCB)FileObject->FsContext;

		ASSERT(Fcb != NULL);

		//
		// This request is not allowed on volumes
		//
		if (Fcb->Identifier.Type == FFSVCB)
		{
			FFSBreakPoint();

			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		ASSERT((Fcb->Identifier.Type == FFSFCB) &&
				(Fcb->Identifier.Size == sizeof(FFS_FCB)));

		if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
		{
			Status = STATUS_FILE_DELETED;
			__leave;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		ASSERT(Ccb != NULL);

		ASSERT((Ccb->Identifier.Type == FFSCCB) &&
				(Ccb->Identifier.Size == sizeof(FFS_CCB)));

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		FileInformationClass =
			IoStackLocation->Parameters.SetFile.FileInformationClass;

		Length = IoStackLocation->Parameters.SetFile.Length;

		Buffer = Irp->AssociatedIrp.SystemBuffer;

		if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
		{
			if (FileInformationClass == FileDispositionInformation ||
					FileInformationClass == FileRenameInformation ||
					FileInformationClass == FileLinkInformation)
			{
				if (!ExAcquireResourceExclusiveLite(
							&Vcb->MainResource,
							IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				VcbResourceAcquired = TRUE;
			}
		}
		else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			FcbMainResourceAcquired = TRUE;
		}

		if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
		{
			if (FileInformationClass != FilePositionInformation)
			{
				Status = STATUS_MEDIA_WRITE_PROTECTED;
				__leave;
			}
		}

		if (FileInformationClass == FileDispositionInformation ||
				FileInformationClass == FileRenameInformation ||
				FileInformationClass == FileLinkInformation ||
				FileInformationClass == FileAllocationInformation ||
				FileInformationClass == FileEndOfFileInformation)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Fcb->PagingIoResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			FcbPagingIoResourceAcquired = TRUE;
		}

		/*        
		if (FileInformationClass != FileDispositionInformation 
			 && FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
		{
			Status = STATUS_DELETE_PENDING;
			__leave;
		}
		*/

		switch (FileInformationClass)
		{
			case FileBasicInformation:
				{
					PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION)Buffer;

					if (FS_VERSION == 1)
					{
						PFFSv1_INODE dinode1 = Fcb->dinode1;

						if(FBI->CreationTime.QuadPart)
						{
							dinode1->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
						}

						if(FBI->LastAccessTime.QuadPart)
						{
							dinode1->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
						}

						if(FBI->LastWriteTime.QuadPart)
						{
							dinode1->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
						}

						if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) 
						{
							FFSSetReadOnly(Fcb->dinode1->di_mode);
							SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
						}
						else
						{
							FFSSetWritable(Fcb->dinode1->di_mode);
							ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
						}

						if(FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode1))
						{
							Status = STATUS_SUCCESS;
						}

						if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) 
						{
							SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
						} 
						else 
						{
							ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
						}
					}
					else
					{
						PFFSv2_INODE dinode2 = Fcb->dinode2;

						if(FBI->CreationTime.QuadPart)
						{
							dinode2->di_ctime = (ULONG)(FFSInodeTime(FBI->CreationTime));
						}

						if(FBI->LastAccessTime.QuadPart)
						{
							dinode2->di_atime = (ULONG)(FFSInodeTime(FBI->LastAccessTime));
						}

						if(FBI->LastWriteTime.QuadPart)
						{
							dinode2->di_mtime = (ULONG)(FFSInodeTime(FBI->LastWriteTime));
						}

						if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) 
						{
							FFSSetReadOnly(Fcb->dinode2->di_mode);
							SetFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
						}
						else
						{
							FFSSetWritable(Fcb->dinode2->di_mode);
							ClearFlag(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
						}

						if(FFSv2SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, dinode2))
						{
							Status = STATUS_SUCCESS;
						}

						if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) 
						{
							SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
						} 
						else 
						{
							ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
						}
					}

					NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
						FILE_NOTIFY_CHANGE_CREATION |
						FILE_NOTIFY_CHANGE_LAST_ACCESS |
						FILE_NOTIFY_CHANGE_LAST_WRITE ;

					Status = STATUS_SUCCESS;
				}
				break;

			case FileAllocationInformation:
				{
					PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;

					if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
					{
						Status = STATUS_INVALID_DEVICE_REQUEST;
						__leave;
					}

					if (FAI->AllocationSize.QuadPart == 
							Fcb->Header.AllocationSize.QuadPart)
					{
						Status = STATUS_SUCCESS;
					}
					else if (FAI->AllocationSize.QuadPart >
							Fcb->Header.AllocationSize.QuadPart)
					{
						if(FFSExpandFile(IrpContext,
									Vcb, Fcb,
									&(FAI->AllocationSize)))
						{
							if (FFSv1SaveInode(IrpContext,
										Vcb,
										Fcb->FFSMcb->Inode,
										Fcb->dinode1))
							{
								Status = STATUS_SUCCESS;
							}
						}
						else
						{
							Status = STATUS_INSUFFICIENT_RESOURCES;
						}
					}
					else
					{
						if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) 
						{
							LARGE_INTEGER EndOfFile;

							EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
								(LONGLONG)(Vcb->BlockSize - 1);

							if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
							{
								if (FAI->AllocationSize.QuadPart < 
										Fcb->Header.FileSize.QuadPart)
								{
									Fcb->Header.FileSize.QuadPart = 
										FAI->AllocationSize.QuadPart;
								}

								FFSv1SaveInode(IrpContext,
										Vcb,
										Fcb->FFSMcb->Inode,
										Fcb->dinode1);

								Status = STATUS_SUCCESS;
							}
						}
						else
						{
							Status = STATUS_USER_MAPPED_FILE;
							__leave;
						}
					}

					if (NT_SUCCESS(Status))
					{
						CcSetFileSizes(FileObject, 
								(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
						SetFlag(FileObject->Flags, FO_FILE_MODIFIED);

						NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
							FILE_NOTIFY_CHANGE_LAST_WRITE ;

					}

				}
				break;

			case FileEndOfFileInformation:
				{
					PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;

					BOOLEAN CacheInitialized = FALSE;

					if (IsDirectory(Fcb))
					{
						Status = STATUS_INVALID_DEVICE_REQUEST;
						__leave;
					}

					if (FEOFI->EndOfFile.HighPart != 0)
					{
						Status = STATUS_INVALID_PARAMETER;
						__leave;
					}


					if (IoStackLocation->Parameters.SetFile.AdvanceOnly)
					{
						Status = STATUS_SUCCESS;
						__leave;
					}

					if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
							(FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
							!FlagOn(Irp->Flags, IRP_PAGING_IO)) {

						ASSERT(!FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE));

						CcInitializeCacheMap(
								FileObject,
								(PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
								FALSE,
								&(FFSGlobal->CacheManagerNoOpCallbacks),
								Fcb);

						CacheInitialized = TRUE;
					}

					if (FEOFI->EndOfFile.QuadPart == 
							Fcb->Header.AllocationSize.QuadPart)
					{
						Status = STATUS_SUCCESS;
					}
					else if (FEOFI->EndOfFile.QuadPart > 
							Fcb->Header.AllocationSize.QuadPart)
					{
						LARGE_INTEGER FileSize = Fcb->Header.FileSize;

						if(FFSExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile)))
						{
							{
								Fcb->Header.FileSize.QuadPart = 
									FEOFI->EndOfFile.QuadPart;
								Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;
								Fcb->Header.ValidDataLength.QuadPart = 
									(LONGLONG)(0x7fffffffffffffff);
							}

							if (FFSv1SaveInode(IrpContext,
										Vcb,
										Fcb->FFSMcb->Inode,
										Fcb->dinode1))
							{
								Status = STATUS_SUCCESS;
							}
						}
						else
						{
							Status = STATUS_INSUFFICIENT_RESOURCES;
						}


						if (NT_SUCCESS(Status))
						{
							CcSetFileSizes(FileObject, 
									(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);

							FFSZeroHoles(IrpContext, 
									Vcb, FileObject, 
									FileSize.QuadPart,
									Fcb->Header.AllocationSize.QuadPart - 
									FileSize.QuadPart);

							NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
								FILE_NOTIFY_CHANGE_LAST_WRITE ;

						}
					}
					else
					{
						if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile))) 
						{
							LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;

							EndOfFile.QuadPart = EndOfFile.QuadPart + 
								(LONGLONG)(Vcb->BlockSize - 1);

							if(FFSTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile)))
							{
								Fcb->Header.FileSize.QuadPart = 
									FEOFI->EndOfFile.QuadPart;
								Fcb->dinode1->di_size = (ULONG)FEOFI->EndOfFile.QuadPart;

								FFSv1SaveInode(IrpContext,
										Vcb,
										Fcb->FFSMcb->Inode,
										Fcb->dinode1);

								Status = STATUS_SUCCESS;
							}
						}
						else
						{
							Status = STATUS_USER_MAPPED_FILE;
							__leave;
						}

						if (NT_SUCCESS(Status))
						{
							CcSetFileSizes(FileObject, 
									(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));

							SetFlag(FileObject->Flags, FO_FILE_MODIFIED);

							NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
								FILE_NOTIFY_CHANGE_LAST_WRITE ;

						}
					}
				}

				break;

			case FileDispositionInformation:
				{
					PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;

					Status = FFSSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
				}

				break;

			case FileRenameInformation:
				{
					Status = FFSSetRenameInfo(IrpContext, Vcb, Fcb);
				}

				break;

				//
				// This is the only set file information request supported on read
				// only file systems
				//
			case FilePositionInformation:
				{
					PFILE_POSITION_INFORMATION FilePositionInformation;

					if (Length < sizeof(FILE_POSITION_INFORMATION))
					{
						Status = STATUS_INVALID_PARAMETER;
						__leave;
					}

					FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;

					if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
							(FilePositionInformation->CurrentByteOffset.LowPart &
							 DeviceObject->AlignmentRequirement))
					{
						Status = STATUS_INVALID_PARAMETER;
						__leave;
					}

					FileObject->CurrentByteOffset =
						FilePositionInformation->CurrentByteOffset;

					Status = STATUS_SUCCESS;
					__leave;
				}

				break;

			default:
				Status = STATUS_INVALID_INFO_CLASS;
		}
	}
	__finally
	{

		if (FcbPagingIoResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->PagingIoResource,
					ExGetCurrentResourceThread());
		}

		if (NT_SUCCESS(Status) && (NotifyFilter != 0))
		{
			FFSNotifyReportChange(
					IrpContext,
					Vcb,
					Fcb,
					NotifyFilter,
					FILE_ACTION_MODIFIED);

		}

		if (FcbMainResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Fcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (VcbResourceAcquired)
		{
			ExReleaseResourceForThreadLite(
					&Vcb->MainResource,
					ExGetCurrentResourceThread());
		}

		if (!IrpContext->ExceptionInProgress)
		{
			if (Status == STATUS_PENDING)
			{
				FFSQueueRequest(IrpContext);
			}
			else
			{
				FFSCompleteIrpContext(IrpContext,  Status);
			}
		}
	}

	return Status;
}


BOOLEAN
FFSExpandFile(
	PFFS_IRP_CONTEXT IrpContext, 
	PFFS_VCB         Vcb,
	PFFS_FCB         Fcb,
	PLARGE_INTEGER   AllocationSize)
{
	ULONG   dwRet = 0;
	BOOLEAN bRet = TRUE;

	if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart)
	{
		return TRUE;
	}

	if (((LONGLONG)SUPER_BLOCK->fs_size - (LONGLONG)SUPER_BLOCK->fs_dsize) * Vcb->BlockSize <=
			(AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart))
	{
		FFSPrint((DBG_ERROR, "FFSExpandFile: There is no enough disk space available.\n"));
		return FALSE;
	}

	while (bRet && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart))
	{
		bRet = FFSExpandInode(IrpContext, Vcb, Fcb, &dwRet);
	}

	return bRet;
}


BOOLEAN
FFSTruncateFile(
	PFFS_IRP_CONTEXT IrpContext,
	PFFS_VCB         Vcb,
	PFFS_FCB         Fcb,
	PLARGE_INTEGER   AllocationSize)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -