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

📄 create.c

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

			if (!Fcb)
			{
				if (FS_VERSION == 1)
				{
					Fcb = FFSv1AllocateFcb(Vcb, FFSMcb, dinode1);
					bFcbAllocated = TRUE;
				}
				else
				{
					Fcb = FFSv2AllocateFcb(Vcb, FFSMcb, dinode2);
					bFcbAllocated = TRUE;
				}
			}
		}

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

			if (FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
			{
				Status = STATUS_DELETE_PENDING;
				__leave;
			}

			if (bCreated)
			{
				//
				//  This file is just created.
				//

				if (DirectoryFile)
				{
					UNICODE_STRING EntryName;
					USHORT  NameBuf[6];

					RtlZeroMemory(&NameBuf, 6 * sizeof(USHORT));

					EntryName.Length = EntryName.MaximumLength = 2;
					EntryName.Buffer = &NameBuf[0];
					NameBuf[0] = (USHORT)'.';

					FFSAddEntry(IrpContext, Vcb, Fcb,
							DT_DIR,
							Fcb->FFSMcb->Inode,
							&EntryName);

					if (FS_VERSION == 1)
					{
						FFSv1SaveInode(IrpContext, Vcb,
								Fcb->FFSMcb->Inode,
								Fcb->dinode1);
					}
					else
					{
						FFSv2SaveInode(IrpContext, Vcb,
								Fcb->FFSMcb->Inode,
								Fcb->dinode2);
					}

					EntryName.Length = EntryName.MaximumLength = 4;
					EntryName.Buffer = &NameBuf[0];
					NameBuf[0] = NameBuf[1] = (USHORT)'.';

					FFSAddEntry(IrpContext, Vcb, Fcb,
							DT_DIR,
							Fcb->FFSMcb->Parent->Inode,
							&EntryName);

					if (FS_VERSION == 1)
					{
						FFSv1SaveInode(IrpContext, Vcb,
								Fcb->FFSMcb->Inode,
								Fcb->dinode1);
					}
					else
					{
						FFSv2SaveInode(IrpContext, Vcb,
								Fcb->FFSMcb->Inode,
								Fcb->dinode2);
					}
				}
				else
				{
					if (!FFSExpandFile(
								IrpContext, Vcb, Fcb,
								&(Irp->Overlay.AllocationSize)))
					{
						Status = STATUS_INSUFFICIENT_RESOURCES;
						__leave;
					}
				}
			}
			else
			{
				//
				//  This file alreayd exists.
				//

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

					if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
					{
						Status = STATUS_MEDIA_WRITE_PROTECTED;

						IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
								Vcb->Vpb->RealDevice);

						SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);

						FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
					}

					SetFlag(Fcb->Flags, FCB_DELETE_ON_CLOSE);
				}
				else
				{
					//
					// Just to Open file (Open/OverWrite ...)
					//

					if ((!IsDirectory(Fcb)) && (IsFlagOn(IrpSp->FileObject->Flags,
									FO_NO_INTERMEDIATE_BUFFERING)))
					{
						Fcb->Header.IsFastIoPossible = FastIoIsPossible;

						if (IsFlagOn(IrpSp->FileObject->Flags, FO_CACHE_SUPPORTED) &&
								(Fcb->SectionObject.DataSectionObject != NULL))
						{
							if (Fcb->NonCachedOpenCount == Fcb->OpenHandleCount)
							{
								/* IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) */

								if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
								{
									CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
									ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
								}

								CcPurgeCacheSection(&Fcb->SectionObject,
										NULL,
										0,
										FALSE);
							}
						}
					}
				}
			}

			if (!IsDirectory(Fcb))
			{
				if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
				{
					if ((CreateDisposition == FILE_SUPERSEDE) && !IsPagingFile)
					{
						DesiredAccess |= DELETE;
					}
					else if (((CreateDisposition == FILE_OVERWRITE) ||
								(CreateDisposition == FILE_OVERWRITE_IF)) && !IsPagingFile)
					{
						DesiredAccess |= (FILE_WRITE_DATA | FILE_WRITE_EA |
								FILE_WRITE_ATTRIBUTES);
					}
				}
			}

			if (Fcb->OpenHandleCount > 0) 
			{
				Status = IoCheckShareAccess(DesiredAccess,
						ShareAccess,
						IrpSp->FileObject,
						&(Fcb->ShareAccess),
						TRUE);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}
			} 
			else 
			{
				IoSetShareAccess(DesiredAccess,
						ShareAccess,
						IrpSp->FileObject,
						&(Fcb->ShareAccess));
			}

			Ccb = FFSAllocateCcb();

			Fcb->OpenHandleCount++;
			Fcb->ReferenceCount++;

			if (IsFlagOn(IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING))
			{
				Fcb->NonCachedOpenCount++;
			}

			Vcb->OpenFileHandleCount++;
			Vcb->ReferenceCount++;

			IrpSp->FileObject->FsContext = (void*)Fcb;
			IrpSp->FileObject->FsContext2 = (void*) Ccb;
			IrpSp->FileObject->PrivateCacheMap = NULL;
			IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
			IrpSp->FileObject->Vpb = Vcb->Vpb;

			Status = STATUS_SUCCESS;

			FFSPrint((DBG_INFO, "FFSCreateFile: %s OpenCount: %u ReferCount: %u\n",
						Fcb->AnsiFileName.Buffer, Fcb->OpenHandleCount, Fcb->ReferenceCount));

			if (!IsDirectory(Fcb) && !NoIntermediateBuffering)
			{
				IrpSp->FileObject->Flags |= FO_CACHE_SUPPORTED;
			}

			if (!bCreated && !IsDirectory(Fcb))
			{
				if (DeleteOnClose || 
						IsFlagOn(DesiredAccess, FILE_WRITE_DATA) || 
						(CreateDisposition == FILE_OVERWRITE) ||
						(CreateDisposition == FILE_OVERWRITE_IF))
				{
					if (!MmFlushImageSection(&Fcb->SectionObject,
								MmFlushForWrite))
					{

						Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
							STATUS_SHARING_VIOLATION;
						__leave;
					}
				}

				if ((CreateDisposition == FILE_SUPERSEDE) ||
						(CreateDisposition == FILE_OVERWRITE) ||
						(CreateDisposition == FILE_OVERWRITE_IF))
				{
					BOOLEAN bRet;

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

					if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
					{
						IoSetHardErrorOrVerifyDevice(IrpContext->Irp,
								Vcb->Vpb->RealDevice);
						SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);

						FFSRaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED);
					}

					Status = FFSSupersedeOrOverWriteFile(IrpContext,
							Vcb,
							Fcb,
							CreateDisposition);

					if (NT_SUCCESS(Status))
					{
						__leave;
					}

					bRet = FFSExpandFile(IrpContext,
							Vcb,
							Fcb,
							&(Irp->Overlay.AllocationSize));

					if (!bRet)
					{
						Status = STATUS_DISK_FULL;
						__leave;
					}

					FFSNotifyReportChange(
							IrpContext,
							Vcb,
							Fcb,
							FILE_NOTIFY_CHANGE_LAST_WRITE |
							FILE_NOTIFY_CHANGE_ATTRIBUTES |
							FILE_NOTIFY_CHANGE_SIZE,
							FILE_ACTION_MODIFIED);


					if (CreateDisposition == FILE_SUPERSEDE)
					{
						Irp->IoStatus.Information = FILE_SUPERSEDED;
					}
					else
					{
						Irp->IoStatus.Information = FILE_OVERWRITTEN;
					}
				}
			}
		}
	}

	__finally
	{
		if (FileName.Buffer)
			ExFreePool(FileName.Buffer);

		if (bParentFcbCreated)
		{
			ParentFcb->ReferenceCount--;
		}

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

		if (!bFcbAllocated)
		{
			if (FS_VERSION == 1)
			{
				if (dinode1)
					ExFreePool(dinode1);
			}
			else
			{
				if (dinode2)
					ExFreePool(dinode2);
			}
		}
		else
		{
			if (FS_VERSION == 1)
			{
				if (!Fcb && dinode1)
					ExFreePool(dinode1);
			}
			else
			{
				if (!Fcb && dinode2)
					ExFreePool(dinode2);
			}
		}
	}

	return Status;
}


NTSTATUS
FFSCreateVolume(
	PFFS_IRP_CONTEXT IrpContext,
	PFFS_VCB         Vcb)
{
	PIO_STACK_LOCATION  IrpSp;
	PIRP                Irp;

	NTSTATUS            Status;

	ACCESS_MASK         DesiredAccess;
	ULONG               ShareAccess;

	ULONG               Options;
	BOOLEAN             DirectoryFile;
	BOOLEAN             OpenTargetDirectory;

	ULONG               CreateDisposition;

	Irp = IrpContext->Irp;
	IrpSp = IoGetCurrentIrpStackLocation(Irp);

	Options  = IrpSp->Parameters.Create.Options;

	DirectoryFile = IsFlagOn(Options, FILE_DIRECTORY_FILE);
	OpenTargetDirectory = IsFlagOn(IrpSp->Flags, SL_OPEN_TARGET_DIRECTORY);

	CreateDisposition = (Options >> 24) & 0x000000ff;

	DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
	ShareAccess   = IrpSp->Parameters.Create.ShareAccess;

	if (DirectoryFile)
	{
		return STATUS_NOT_A_DIRECTORY;
	}

	if (OpenTargetDirectory)
	{
		return STATUS_INVALID_PARAMETER;
	}

	if ((CreateDisposition != FILE_OPEN) && 
			(CreateDisposition != FILE_OPEN_IF)) 
	{
		return STATUS_ACCESS_DENIED;
	}

	Status = STATUS_SUCCESS;

	if (Vcb->OpenHandleCount > 0) 
	{
		Status = IoCheckShareAccess(DesiredAccess, ShareAccess,
				IrpSp->FileObject,
				&(Vcb->ShareAccess), TRUE);

		if (!NT_SUCCESS(Status)) 
		{
			goto errorout;
		}
	} 
	else 
	{
		IoSetShareAccess(DesiredAccess, ShareAccess,
				IrpSp->FileObject,
				&(Vcb->ShareAccess));
	}

	if (FlagOn(DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))
	{
		ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
		FFSFlushFiles(Vcb, FALSE);
		FFSFlushVolume(Vcb, FALSE);
		ExReleaseResource(&Vcb->MainResource);
	}

	{
		PFFS_CCB Ccb = FFSAllocateCcb();

		if (Ccb == NULL)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			goto errorout;
		}

		IrpSp->FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
		IrpSp->FileObject->FsContext  = Vcb;
		IrpSp->FileObject->FsContext2 = Ccb;

		Vcb->ReferenceCount++;
		Vcb->OpenHandleCount++;

		Irp->IoStatus.Information = FILE_OPENED;
	}

errorout:

	return Status;
}


NTSTATUS
FFSCreate(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	PDEVICE_OBJECT      DeviceObject;
	PIRP                Irp;
	PIO_STACK_LOCATION  IrpSp;
	PFFS_VCB            Vcb = 0;
	NTSTATUS            Status = STATUS_OBJECT_NAME_NOT_FOUND;
	PFFS_FCBVCB         Xcb = NULL;

	DeviceObject = IrpContext->DeviceObject;

	Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

#if 0
	/* 靛扼捞滚啊 肺靛 登菌绰瘤 八荤且 锭 付款飘啊 登绢 乐瘤 臼篮
	   版快档 乐扁 锭巩俊 肛眠搁 救凳. */
	ASSERT(IsMounted(Vcb));
#endif	

	Irp = IrpContext->Irp;

	IrpSp = IoGetCurrentIrpStackLocation(Irp);

	Xcb = (PFFS_FCBVCB)(IrpSp->FileObject->FsContext);

	if (DeviceObject == FFSGlobal->DeviceObject)
	{
		FFSPrint((DBG_INFO, "FFSCreate: Create on main device object.\n"));

		Status = STATUS_SUCCESS;

		Irp->IoStatus.Information = FILE_OPENED;

		FFSUnpinRepinnedBcbs(IrpContext);

		FFSCompleteIrpContext(IrpContext, Status);        

		return Status;

	}

	__try
	{
		if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
		{
			Status = STATUS_ACCESS_DENIED;

			if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
			{
				Status = STATUS_VOLUME_DISMOUNTED;
			}

			__leave;
		}

		if (((IrpSp->FileObject->FileName.Length == 0) &&
					(IrpSp->FileObject->RelatedFileObject == NULL)) || 
				(Xcb && Xcb->Identifier.Type == FFSVCB))
		{
			Status = FFSCreateVolume(IrpContext, Vcb);
		}
		else
		{
			Status = FFSCreateFile(IrpContext, Vcb);
		}
	}

	__finally
	{

		if (!IrpContext->ExceptionInProgress)
		{
			FFSUnpinRepinnedBcbs(IrpContext);

			FFSCompleteIrpContext(IrpContext, Status);
		}
	}

	return Status;
}


NTSTATUS
FFSCreateInode(
	PFFS_IRP_CONTEXT    IrpContext,
	PFFS_VCB            Vcb,
	PFFS_FCB            ParentFcb,
	ULONG               Type,
	ULONG               FileAttr,
	PUNICODE_STRING     FileName)
{
	NTSTATUS    Status;
	ULONG       Inode;
	ULONG       Group;

	FFSv1_INODE dinode1;

	RtlZeroMemory(&dinode1, DINODE1_SIZE);

	Group = (ParentFcb->FFSMcb->Inode - 1) / BLOCKS_PER_GROUP;

	FFSPrint((DBG_INFO,
				"FFSCreateInode: %S in %S(Inode=%xh)\n",
				FileName->Buffer, 
				ParentFcb->FFSMcb->ShortName.Buffer, 
				ParentFcb->FFSMcb->Inode));

	Status = FFSNewInode(IrpContext, Vcb, Group,Type, &Inode);

	if (!NT_SUCCESS(Status))
	{
		goto errorout;
	}

	Status = FFSAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName);

	if (!NT_SUCCESS(Status))
	{
		FFSBreakPoint();
		FFSFreeInode(IrpContext, Vcb, Inode, Type);

		goto errorout;
	}

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

	dinode1.di_ctime = ParentFcb->dinode1->di_mtime;
	dinode1.di_mode =  0x1FF;

	if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY))
	{
		FFSSetReadOnly(dinode1.di_mode);
	}

	if (Type == DT_DIR)
	{
		SetFlag(dinode1.di_mode, IFDIR);

		dinode1.di_nlink = 2;
	}
	else
	{
		dinode1.di_nlink = 1;
		SetFlag(dinode1.di_mode, IFLNK);
	}

	FFSv1SaveInode(IrpContext, Vcb, Inode, &dinode1);

	FFSPrint((DBG_INFO, "FFSCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type));

errorout:

	return Status;
}


NTSTATUS
FFSSupersedeOrOverWriteFile(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFFS_FCB         Fcb,
	IN ULONG            Disposition)
{
	LARGE_INTEGER   CurrentTime;
	LARGE_INTEGER   AllocationSize;
	NTSTATUS        Status = STATUS_SUCCESS;

	BOOLEAN         bRet = FALSE;

	KeQuerySystemTime(&CurrentTime);

	AllocationSize.QuadPart = (LONGLONG)0;

	if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) 
	{
		Status = STATUS_USER_MAPPED_FILE;

		return Status;
	}

	bRet = FFSTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);

	if (bRet)
	{
		Fcb->Header.AllocationSize.QuadPart = 
			Fcb->Header.FileSize.QuadPart = (LONGLONG)0;

		Fcb->dinode1->di_size = 0;

		if (Disposition == FILE_SUPERSEDE)
			Fcb->dinode1->di_ctime = FFSInodeTime(CurrentTime);

		Fcb->dinode1->di_atime =
			Fcb->dinode1->di_mtime = FFSInodeTime(CurrentTime);
	}
	else
	{
		if (Fcb->dinode1->di_size > Fcb->Header.AllocationSize.LowPart)
			Fcb->dinode1->di_size = Fcb->Header.AllocationSize.LowPart;

		Fcb->Header.FileSize.QuadPart = (LONGLONG)Fcb->dinode1->di_size;

		Status = STATUS_UNSUCCESSFUL;
	}

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

	return Status;
}

⌨️ 快捷键说明

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