📄 create.c
字号:
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 + -