📄 create.c
字号:
NTSTATUS
RfsdCreate (IN PRFSD_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PRFSD_VCB Vcb = 0;
NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
PRFSD_FCBVCB Xcb = NULL;
DeviceObject = IrpContext->DeviceObject;
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(IsMounted(Vcb));
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Xcb = (PRFSD_FCBVCB) (IrpSp->FileObject->FsContext);
if (DeviceObject == RfsdGlobal->DeviceObject) {
RfsdPrint((DBG_INFO, "RfsdCreate: Create on main device object.\n"));
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
RfsdUnpinRepinnedBcbs(IrpContext);
RfsdCompleteIrpContext(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 == RFSDVCB) ) {
Status = RfsdCreateVolume(IrpContext, Vcb);
} else {
Status = RfsdCreateFile(IrpContext, Vcb);
}
} __finally {
if (!IrpContext->ExceptionInProgress) {
RfsdUnpinRepinnedBcbs(IrpContext);
RfsdCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
#if DISABLED // WRITE SUPPORT ONLY?
NTSTATUS
RfsdCreateInode(
PRFSD_IRP_CONTEXT IrpContext,
PRFSD_VCB Vcb,
PRFSD_FCB ParentFcb,
ULONG Type,
ULONG FileAttr,
PUNICODE_STRING FileName)
{
DbgBreak();
NTSTATUS Status;
ULONG Inode;
ULONG Group;
RFSD_INODE RfsdIno;
RtlZeroMemory(&RfsdIno, sizeof(RFSD_INODE));
DbgBreak();
#if DISABLED
Group = (ParentFcb->RfsdMcb->Inode - 1) / BLOCKS_PER_GROUP;
#endif
RfsdPrint(( DBG_INFO,
"RfsdCreateInode: %S in %S(Key=%x,%xh)\n",
FileName->Buffer,
ParentFcb->RfsdMcb->ShortName.Buffer,
ParentFcb->RfsdMcb->Key.k_dir_id, ParentFcb->RfsdMcb->Key.k_objectid));
Status = RfsdNewInode(IrpContext, Vcb, Group,Type, &Inode);
if (!NT_SUCCESS(Status)) {
goto errorout;
}
Status = RfsdAddEntry(IrpContext, Vcb, ParentFcb, Type, Inode, FileName);
if (!NT_SUCCESS(Status)) {
DbgBreak();
RfsdFreeInode(IrpContext, Vcb, Inode, Type);
goto errorout;
}
RfsdSaveInode(IrpContext, Vcb, ParentFcb->RfsdMcb->Inode, ParentFcb->Inode);
RfsdIno.i_ctime = ParentFcb->Inode->i_mtime;
RfsdIno.i_mode = ( S_IPERMISSION_MASK &
ParentFcb->Inode->i_mode );
RfsdIno.i_uid = ParentFcb->Inode->i_uid;
RfsdIno.i_gid = ParentFcb->Inode->i_gid;
//~ RfsdIno.i_dir_acl = ParentFcb->Inode->i_dir_acl;
//~ RfsdIno.i_file_acl = ParentFcb->Inode->i_file_acl;
RfsdIno.u.i_generation = ParentFcb->Inode->u.i_generation;
//~ RfsdIno.osd2 = ParentFcb->Inode->osd2;
if (IsFlagOn(FileAttr, FILE_ATTRIBUTE_READONLY)) {
RfsdSetReadOnly(RfsdIno.i_mode);
}
if (Type == RFSD_FT_DIR) {
RfsdIno.i_mode |= S_IFDIR;
RfsdIno.i_links_count = 2;
} else if (Type == RFSD_FT_REG_FILE) {
RfsdIno.i_mode |= S_IFREG;
RfsdIno.i_links_count = 1;
} else {
DbgBreak();
RfsdIno.i_links_count = 1;
}
RfsdSaveInode(IrpContext, Vcb, Inode, &RfsdIno);
RfsdPrint((DBG_INFO, "RfsdCreateInode: New Inode = %xh (Type=%xh)\n", Inode, Type));
errorout:
return Status;
}
#endif
#if DISABLED
NTSTATUS
RfsdSupersedeOrOverWriteFile(
PRFSD_IRP_CONTEXT IrpContext,
PRFSD_VCB Vcb,
PRFSD_FCB Fcb,
ULONG Disposition)
{
DbgBreak();
LARGE_INTEGER CurrentTime;
LARGE_INTEGER AllocationSize;
NTSTATUS Status = STATUS_SUCCESS;
KeQuerySystemTime(&CurrentTime);
AllocationSize.QuadPart = (LONGLONG)0;
if (!MmCanFileBeTruncated(&(Fcb->SectionObject), &(AllocationSize))) {
Status = STATUS_USER_MAPPED_FILE;
return Status;
}
DbgBreak();
#if DISABLED
Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
#endif
if (NT_SUCCESS(Status)) {
Fcb->Header.AllocationSize.QuadPart =
Fcb->Header.FileSize.QuadPart = (LONGLONG) 0;
Fcb->Inode->i_size = 0;
if (S_ISREG(Fcb->Inode->i_mode)) {
KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
//~Fcb->Inode->i_size_high = 0;
}
if (Disposition == FILE_SUPERSEDE)
Fcb->Inode->i_ctime = RfsdInodeTime(CurrentTime);
Fcb->Inode->i_atime =
Fcb->Inode->i_mtime = RfsdInodeTime(CurrentTime);
} else {
LARGE_INTEGER iSize;
iSize.QuadPart = (LONGLONG) Fcb->Inode->i_size;
if (S_ISREG(Fcb->Inode->i_mode))
KdPrint(("Reminder: Fcb->Inode->i_size_high = 0;\n"));
//~ iSize.HighPart = (LONG)(Fcb->Inode->i_size_high);
if (iSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
iSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
Fcb->Header.FileSize.QuadPart = iSize.QuadPart;
Fcb->Inode->i_size = iSize.LowPart;
//~ Fcb->Inode->i_size_high = (ULONG) iSize.HighPart;
}
RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
return Status;
}
#endif
/**
Searches to find if the name if is located in the dentry span within the block.
STATUS_SUCCESS if the name was not found, but processing should continue
STATUS_EVENT_DONE if the name was found, and processing should stop
*/
NTSTATUS
RfsdScanDirCallback(
ULONG BlockNumber,
PVOID pContext )
{
PRFSD_SCANDIR_CALLBACK_CONTEXT pCallbackContext = (PRFSD_SCANDIR_CALLBACK_CONTEXT) pContext;
RFSD_KEY_IN_MEMORY DirectoryKey;
PUCHAR pBlockBuffer = NULL;
PRFSD_ITEM_HEAD pDirectoryItemHeader = NULL;
PUCHAR pDirectoryItemBuffer = NULL;
NTSTATUS Status;
BOOLEAN bFound = FALSE;
PRFSD_DENTRY_HEAD pPrevDentry = NULL;
ULONG idxDentryInSpan = 0;
UNICODE_STRING InodeFileName;
USHORT InodeFileNameLength;
InodeFileName.Buffer = NULL;
RfsdPrint((DBG_FUNC, __FUNCTION__ " invoked on block %i\n", BlockNumber));
__try {
// Load the block
pBlockBuffer = RfsdAllocateAndLoadBlock(pCallbackContext->Vcb, BlockNumber);
if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; }
// Construct the item key to search for
DirectoryKey = *(pCallbackContext->pDirectoryKey);
DirectoryKey.k_type = RFSD_KEY_TYPE_v2_DIRENTRY;
// Get the item header and its information
Status = RfsdFindItemHeaderInBlock(
pCallbackContext->Vcb, &DirectoryKey, pBlockBuffer,
( &pDirectoryItemHeader ), //<
&CompareKeysWithoutOffset
);
// If this block doesn't happen to contain a directory item, skip it.
if ( (Status == STATUS_NO_SUCH_MEMBER) || !pDirectoryItemHeader )
{
KdPrint(("Block %i did not contain the appropriate diritem header\n", BlockNumber));
Status = STATUS_SUCCESS; __leave;
}
// Setup the item buffer
pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;
// Allocate the unicode filename buffer
InodeFileName.Buffer = ExAllocatePool(PagedPool, (RFSD_NAME_LEN + 1) * 2 );
if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; }
while (!bFound && (idxDentryInSpan < pDirectoryItemHeader->u.ih_entry_count) ) {
OEM_STRING OemName;
//
// reading dir entries from Dcb
//
PRFSD_DENTRY_HEAD pCurrentDentry = (PRFSD_DENTRY_HEAD) (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD)));
// Skip the directory entry for the parent of the root directory (because it should not be shown, and has no stat data)
// (NOTE: Any change made here should also be mirrored in RfsdDirControlCallback)
if (pCurrentDentry->deh_dir_id == 0 /*&& pCurrentDentry->deh_objectid == 1*/)
{ goto ProcessNextEntry; }
// Retrieve the filename of the loaded directory entry from the buffer (encoded with the codepage)
// NOTE: The filename is not gauranteed to be null-terminated, and so the end may implicitly be the start of the previous entry.
OemName.Buffer = (PUCHAR) pDirectoryItemBuffer + pCurrentDentry->deh_location;
OemName.MaximumLength = (pPrevDentry ? pPrevDentry->deh_location : // The end of this entry is the start of the previous
pDirectoryItemHeader->ih_item_len // Otherwise this is the first entry, the end of which is the end of the item.
) - pCurrentDentry->deh_location;
OemName.Length = RfsdStringLength(OemName.Buffer, OemName.MaximumLength);
// Convert that name to unicode
{
InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName) + 2;
// If the unicode InodeFileName.Buffer is not large enough, expand it
if (InodeFileName.MaximumLength < InodeFileNameLength)
{
// Free the existing buffer
if (InodeFileName.Buffer) { ExFreePool(InodeFileName.Buffer); }
// Allocate a new larger buffer
InodeFileName.Buffer = ExAllocatePool(PagedPool, InodeFileNameLength );
if (!InodeFileName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; __leave; }
InodeFileName.MaximumLength = InodeFileNameLength;
}
InodeFileName.Length = 0;
RtlZeroMemory( InodeFileName.Buffer, InodeFileNameLength);
Status = RfsdOEMToUnicode(
&InodeFileName,
&OemName );
if (!NT_SUCCESS(Status)) { __leave; }
}
// Compare it to the name we are searching for
if (!RtlCompareUnicodeString(
pCallbackContext->pTargetFilename,
&InodeFileName,
TRUE )) {
// This entry MATCHED! Copy the matching dentry into the output field on the context
bFound = TRUE;
*(pCallbackContext->pMatchingIndex) = (pCallbackContext->idxCurrentDentry * sizeof(RFSD_DENTRY_HEAD));
RtlCopyMemory(pCallbackContext->pMatchingDentry, pCurrentDentry, sizeof(RFSD_DENTRY_HEAD));
RfsdPrint(( DBG_INFO, __FUNCTION__ ": Found: Name=%S Key=%xh,%xh\n",
InodeFileName.Buffer, pCurrentDentry->deh_dir_id, pCurrentDentry->deh_objectid ));
Status = STATUS_EVENT_DONE;
break;
}
ProcessNextEntry:
// Advance to the next directory entry
pPrevDentry = pCurrentDentry;
++idxDentryInSpan;
++(pCallbackContext->idxCurrentDentry);
}
if (!bFound) {
// Indicate success, so that parsing will continue with subsequent blocks.
Status = STATUS_SUCCESS;
}
} __finally {
if (pBlockBuffer) ExFreePool(pBlockBuffer);
if (InodeFileName.Buffer) ExFreePool(InodeFileName.Buffer);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -