📄 create.c
字号:
&InodeFileName,
TRUE))
{
bFound = TRUE;
*Index = dwBytes;
RtlCopyMemory(ffs_dir, pDir, pDir->d_reclen > sizeof(FFS_DIR_ENTRY)
? sizeof(FFS_DIR_ENTRY) : pDir->d_reclen);
Status = STATUS_SUCCESS;
FFSPrint((DBG_VITAL, "FFSv2ScanDir: Found: Name=%S Inode=%xh\n", InodeFileName.Buffer, pDir->d_ino));
}
dwBytes +=pDir->d_reclen;
Offset = (LONGLONG)dwBytes;
}
else
{
if (pDir->d_ino == 0)
{
if (pDir->d_reclen == 0)
{
FFSBreakPoint();
break;
}
else
{
dwBytes +=pDir->d_reclen;
Offset = (LONGLONG)dwBytes;
}
}
else
{
break;
}
}
}
if (!bFound)
{
Status = STATUS_NO_SUCH_FILE;
}
}
__finally
{
if (InodeFileName.Buffer != NULL)
{
ExFreePool(InodeFileName.Buffer);
}
if (pDir)
ExFreePool(pDir);
}
return Status;
}
/*
PFFS_FCB
FFSSearchFcbList(
IN PFFS_VCB Vcb,
IN ULONG inode)
{
BOOLEAN bFound = FALSE;
PLIST_ENTRY Link;
PFFS_FCB TmpFcb;
Link = Vcb->FcbList.Flink;
while (!bFound && Link != &Vcb->FcbList)
{
TmpFcb = CONTAINING_RECORD(Link, FFS_FCB, Next);
if (TmpFcb && TmpFcb->Identifier.Type == FCB)
{
#if DBG
FFSPrint((DBG_INFO, "FFSSearchFcbList: [%s,%xh]\n",
TmpFcb->AnsiFileName.Buffer, TmpFcb->Inode));
#endif
if (TmpFcb->Inode == inode)
{
FFSPrint((DBG_INFO, "FFSSearchMcb: Found FCB for %xh.\n", inode));
bFound = TRUE;
}
}
Link = Link->Flink;
}
if (bFound)
return TmpFcb;
else
return NULL;
}
*/
NTSTATUS
FFSCreateFile(
PFFS_IRP_CONTEXT IrpContext,
PFFS_VCB Vcb)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION IrpSp;
PFFS_FCB Fcb = NULL;
PFFS_MCB FFSMcb = NULL;
PFFS_FCB ParentFcb = NULL;
PFFS_MCB ParentMcb = NULL;
BOOLEAN bParentFcbCreated = FALSE;
PFFS_CCB Ccb = NULL;
PFFSv1_INODE dinode1;
PFFSv2_INODE dinode2;
BOOLEAN VcbResourceAcquired = FALSE;
BOOLEAN bDir = FALSE;
BOOLEAN bFcbAllocated = FALSE;
BOOLEAN bCreated = FALSE;
UNICODE_STRING FileName;
PIRP Irp;
ULONG Options;
ULONG CreateDisposition;
BOOLEAN OpenDirectory;
BOOLEAN OpenTargetDirectory;
BOOLEAN CreateDirectory;
BOOLEAN SequentialOnly;
BOOLEAN NoIntermediateBuffering;
BOOLEAN IsPagingFile;
BOOLEAN DirectoryFile;
BOOLEAN NonDirectoryFile;
BOOLEAN NoEaKnowledge;
BOOLEAN DeleteOnClose;
BOOLEAN TemporaryFile;
BOOLEAN CaseSensitive;
ACCESS_MASK DesiredAccess;
ULONG ShareAccess;
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);
NonDirectoryFile = IsFlagOn(Options, FILE_NON_DIRECTORY_FILE);
SequentialOnly = IsFlagOn(Options, FILE_SEQUENTIAL_ONLY);
NoIntermediateBuffering = IsFlagOn(Options, FILE_NO_INTERMEDIATE_BUFFERING);
NoEaKnowledge = IsFlagOn(Options, FILE_NO_EA_KNOWLEDGE);
DeleteOnClose = IsFlagOn(Options, FILE_DELETE_ON_CLOSE);
CaseSensitive = IsFlagOn(IrpSp->Flags, SL_CASE_SENSITIVE);
TemporaryFile = IsFlagOn(IrpSp->Parameters.Create.FileAttributes,
FILE_ATTRIBUTE_TEMPORARY);
CreateDisposition = (Options >> 24) & 0x000000ff;
IsPagingFile = IsFlagOn(IrpSp->Flags, SL_OPEN_PAGING_FILE);
CreateDirectory = (BOOLEAN)(DirectoryFile &&
((CreateDisposition == FILE_CREATE) ||
(CreateDisposition == FILE_OPEN_IF)));
OpenDirectory = (BOOLEAN)(DirectoryFile &&
((CreateDisposition == FILE_OPEN) ||
(CreateDisposition == FILE_OPEN_IF)));
DesiredAccess = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
ShareAccess = IrpSp->Parameters.Create.ShareAccess;
FileName.Buffer = NULL;
__try
{
ExAcquireResourceExclusiveLite(
&Vcb->MainResource, TRUE);
VcbResourceAcquired = TRUE;
if (Irp->Overlay.AllocationSize.HighPart)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (FS_VERSION == 1)
{
if (!(dinode1 = ExAllocatePoolWithTag(
PagedPool, DINODE1_SIZE, 'EInd')))
{
__leave;
}
RtlZeroMemory(dinode1, sizeof(DINODE1_SIZE));
}
else
{
if (!(dinode2 = ExAllocatePoolWithTag(
PagedPool, DINODE2_SIZE, 'EInd')))
{
__leave;
}
RtlZeroMemory(dinode2, sizeof(DINODE2_SIZE));
}
FileName.MaximumLength = IrpSp->FileObject->FileName.MaximumLength;
FileName.Length = IrpSp->FileObject->FileName.Length;
FileName.Buffer = ExAllocatePool(PagedPool, FileName.MaximumLength);
if (!FileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(FileName.Buffer, FileName.MaximumLength);
RtlCopyMemory(FileName.Buffer, IrpSp->FileObject->FileName.Buffer, FileName.Length);
if (IrpSp->FileObject->RelatedFileObject)
{
ParentFcb = (PFFS_FCB)(IrpSp->FileObject->RelatedFileObject->FsContext);
}
if ((FileName.Length > sizeof(WCHAR)) &&
(FileName.Buffer[1] == L'\\') &&
(FileName.Buffer[0] == L'\\')) {
FileName.Length -= sizeof(WCHAR);
RtlMoveMemory(&FileName.Buffer[0],
&FileName.Buffer[1],
FileName.Length);
//
// Bad Name if there are still beginning backslashes.
//
if ((FileName.Length > sizeof(WCHAR)) &&
(FileName.Buffer[1] == L'\\') &&
(FileName.Buffer[0] == L'\\'))
{
Status = STATUS_OBJECT_NAME_INVALID;
__leave;
}
}
if (IsFlagOn(Options, FILE_OPEN_BY_FILE_ID))
{
Status = STATUS_NOT_IMPLEMENTED;
__leave;
}
FFSPrint((DBG_INFO, "FFSCreateFile: %S (NameLen=%xh) Paging=%xh Option: %xh.\n",
FileName.Buffer, FileName.Length, IsPagingFile, IrpSp->Parameters.Create.Options));
if (ParentFcb)
{
ParentMcb = ParentFcb->FFSMcb;
}
if (FS_VERSION == 1)
{
Status = FFSv1LookupFileName(
Vcb,
&FileName,
ParentMcb,
&FFSMcb,
dinode1);
}
else
{
Status = FFSv2LookupFileName(
Vcb,
&FileName,
ParentMcb,
&FFSMcb,
dinode2);
}
if (!NT_SUCCESS(Status))
{
UNICODE_STRING PathName;
UNICODE_STRING RealName;
UNICODE_STRING RemainName;
LONG i = 0;
PathName = FileName;
FFSPrint((DBG_INFO, "FFSCreateFile: File %S will be created.\n", PathName.Buffer));
FFSMcb = NULL;
if (PathName.Buffer[PathName.Length / 2 - 1] == L'\\')
{
if (DirectoryFile)
{
PathName.Length -= 2;
PathName.Buffer[PathName.Length / 2] = 0;
}
else
{
Status = STATUS_NOT_A_DIRECTORY;
__leave;
}
}
if (!ParentMcb)
{
if (PathName.Buffer[0] != L'\\')
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
else
{
ParentMcb = Vcb->McbTree;
}
}
Dissecting:
FsRtlDissectName(PathName, &RealName, &RemainName);
if (((RemainName.Length != 0) && (RemainName.Buffer[0] == L'\\')) ||
(RealName.Length >= 256 * sizeof(WCHAR)))
{
Status = STATUS_OBJECT_NAME_INVALID;
__leave;
}
if (RemainName.Length != 0)
{
PFFS_MCB RetMcb;
if (FS_VERSION == 1)
{
Status = FFSv1LookupFileName(
Vcb,
&RealName,
ParentMcb,
&RetMcb,
dinode1);
}
else
{
Status = FFSv2LookupFileName(
Vcb,
&RealName,
ParentMcb,
&RetMcb,
dinode2);
}
if (!NT_SUCCESS(Status))
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
ParentMcb = RetMcb;
PathName = RemainName;
goto Dissecting;
}
if (FsRtlDoesNameContainWildCards(&RealName))
{
Status = STATUS_OBJECT_NAME_INVALID;
__leave;
}
ParentFcb = ParentMcb->FFSFcb;
if (!ParentFcb)
{
if (FS_VERSION == 1)
{
PFFSv1_INODE pTmpInode = ExAllocatePool(PagedPool,
DINODE1_SIZE);
if (!pTmpInode)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
if(!FFSv1LoadInode(Vcb, ParentMcb->Inode, pTmpInode))
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
ParentFcb = FFSv1AllocateFcb(Vcb, ParentMcb, pTmpInode);
if (!ParentFcb)
{
ExFreePool(pTmpInode);
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
}
else
{
PFFSv2_INODE pTmpInode = ExAllocatePool(PagedPool,
DINODE2_SIZE);
if (!pTmpInode)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
if(!FFSv2LoadInode(Vcb, ParentMcb->Inode, pTmpInode))
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
ParentFcb = FFSv2AllocateFcb(Vcb, ParentMcb, pTmpInode);
if (!ParentFcb)
{
ExFreePool(pTmpInode);
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
}
bParentFcbCreated = TRUE;
ParentFcb->ReferenceCount++;
}
// We need to create a new one ?
if ((CreateDisposition == FILE_CREATE) ||
(CreateDisposition == FILE_OPEN_IF) ||
(CreateDisposition == FILE_OVERWRITE_IF))
{
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);
}
if (DirectoryFile)
{
if (TemporaryFile)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
}
if (!ParentFcb)
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
if (DirectoryFile)
{
if (ParentFcb->FFSMcb->Inode == FFS_ROOT_INO)
{
if ((RealName.Length == 0x10) &&
memcmp(RealName.Buffer, L"Recycled\0", 0x10) == 0)
{
SetFlag(IrpSp->Parameters.Create.FileAttributes,
FILE_ATTRIBUTE_READONLY);
}
}
Status = FFSCreateInode(
IrpContext,
Vcb,
ParentFcb,
DT_DIR,
IrpSp->Parameters.Create.FileAttributes,
&RealName);
}
else
{
Status = FFSCreateInode(
IrpContext,
Vcb,
ParentFcb,
DT_REG,
IrpSp->Parameters.Create.FileAttributes,
&RealName);
}
if (NT_SUCCESS(Status))
{
bCreated = TRUE;
Irp->IoStatus.Information = FILE_CREATED;
if (FS_VERSION == 1)
{
Status = FFSv1LookupFileName(
Vcb,
&RealName,
ParentMcb,
&FFSMcb,
dinode1);
}
else
{
Status = FFSv2LookupFileName(
Vcb,
&RealName,
ParentMcb,
&FFSMcb,
dinode2);
}
if (NT_SUCCESS(Status))
{
if (DirectoryFile)
{
FFSNotifyReportChange(
IrpContext,
Vcb,
ParentFcb,
FILE_NOTIFY_CHANGE_DIR_NAME,
FILE_ACTION_ADDED);
}
else
{
FFSNotifyReportChange(
IrpContext,
Vcb,
ParentFcb,
FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_ADDED);
}
}
else
{
FFSBreakPoint();
}
}
else
{
FFSBreakPoint();
}
}
else if (OpenTargetDirectory)
{
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
__leave;
}
if (!ParentFcb)
{
Status = STATUS_OBJECT_PATH_NOT_FOUND;
__leave;
}
RtlZeroMemory(IrpSp->FileObject->FileName.Buffer,
IrpSp->FileObject->FileName.MaximumLength);
IrpSp->FileObject->FileName.Length = RealName.Length;
RtlCopyMemory(IrpSp->FileObject->FileName.Buffer,
RealName.Buffer,
RealName.Length);
Fcb = ParentFcb;
Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
__leave;
}
}
else // File / Dir already exists.
{
if (OpenTargetDirectory)
{
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
__leave;
}
Irp->IoStatus.Information = FILE_EXISTS;
Status = STATUS_SUCCESS;
RtlZeroMemory(IrpSp->FileObject->FileName.Buffer,
IrpSp->FileObject->FileName.MaximumLength);
IrpSp->FileObject->FileName.Length = FFSMcb->ShortName.Length;
RtlCopyMemory(IrpSp->FileObject->FileName.Buffer,
FFSMcb->ShortName.Buffer,
FFSMcb->ShortName.Length);
//Let Mcb pointer to it's parent
FFSMcb = FFSMcb->Parent;
goto Openit;
}
// We can not create if one exists
if (CreateDisposition == FILE_CREATE)
{
Irp->IoStatus.Information = FILE_EXISTS;
Status = STATUS_OBJECT_NAME_COLLISION;
__leave;
}
if(IsFlagOn(FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF))
{
Status = STATUS_OBJECT_NAME_COLLISION;
__leave;
}
if (NonDirectoryFile)
{
Status = STATUS_FILE_IS_A_DIRECTORY;
__leave;
}
if (FFSMcb->Inode == FFS_ROOT_INO)
{
if (DeleteOnClose)
{
Status = STATUS_CANNOT_DELETE;
__leave;
}
if (OpenTargetDirectory)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
}
}
Irp->IoStatus.Information = FILE_OPENED;
}
Openit:
if (FFSMcb)
{
Fcb = FFSMcb->FFSFcb;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -