📄 create.c
字号:
/*
This is a romfs file system driver for Windows NT/2000/XP.
Copyright (C) 1999, 2000, 2001, 2002 Bo Brant閚.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ntifs.h"
#include "fsd.h"
#include "rom_fs.h"
#include "border.h"
#pragma code_seg(FSD_PAGED_CODE)
NTSTATUS
FsdCreate (
IN PFSD_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
DeviceObject = IrpContext->DeviceObject;
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (DeviceObject == FsdGlobalData.DeviceObject)
{
return FsdCreateFs(IrpContext);
}
else if (IrpSp->FileObject->FileName.Length == 0)
{
return FsdCreateVolume(IrpContext);
}
else
{
return FsdCreateFile(IrpContext);
}
}
NTSTATUS
FsdCreateFs (
IN PFSD_IRP_CONTEXT IrpContext
)
{
IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
FsdCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
FsdFreeIrpContext(IrpContext);
return STATUS_SUCCESS;
}
NTSTATUS
FsdCreateVolume (
IN PFSD_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
PFSD_VCB Vcb;
PFILE_OBJECT FileObject;
DeviceObject = IrpContext->DeviceObject;
Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == VCB) &&
(Vcb->Identifier.Size == sizeof(FSD_VCB)));
FileObject = IrpContext->FileObject;
FileObject->FsContext = Vcb;
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE
);
Vcb->ReferenceCount++;
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
FsdCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
FsdFreeIrpContext(IrpContext);
return STATUS_SUCCESS;
}
NTSTATUS
FsdCreateFile (
IN PFSD_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFSD_VCB Vcb = NULL;
PFSD_FCB Fcb;
PFSD_CCB Ccb;
ULONG found_index = 0;
struct romfs_inode* Inode = NULL;
BOOLEAN VcbResourceAcquired = FALSE;
DeviceObject = IrpContext->DeviceObject;
Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
__try
{
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE
);
VcbResourceAcquired = TRUE;
Fcb = FsdLookupFcbByFileName(
Vcb,
&IrpSp->FileObject->FileName
);
if (!Fcb)
{
Inode = FsdAllocatePool(
NonPagedPool,
sizeof(struct romfs_inode) + ROMFS_MAXFN,
'3cFR'
);
if (Inode == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Status = FsdLookupFileName(
Vcb,
&IrpSp->FileObject->FileName,
&found_index,
Inode
);
if (!NT_SUCCESS(Status))
{
KdPrint((
DRIVER_NAME ": STATUS_OBJECT_NAME_NOT_FOUND: %.*S\n",
IrpSp->FileObject->FileName.Length / 2,
IrpSp->FileObject->FileName.Buffer
));
Status = STATUS_OBJECT_NAME_NOT_FOUND;
__leave;
}
Fcb = FsdAllocateFcb(
Vcb,
&IrpSp->FileObject->FileName,
found_index,
Inode
);
if (Fcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
KdPrint((
DRIVER_NAME ": Allocated a new FCB for %s\n",
Fcb->AnsiFileName.Buffer
));
}
if (Fcb->OpenHandleCount >= 1)
{
Status = IoCheckShareAccess(
IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
IrpSp->Parameters.Create.ShareAccess,
IrpSp->FileObject,
&Fcb->ShareAccess,
FALSE
);
if (!NT_SUCCESS(Status))
{
__leave;
}
}
Ccb = FsdAllocateCcb();
if (Ccb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Fcb->OpenHandleCount++;
Vcb->OpenFileHandleCount++;
Fcb->ReferenceCount++;
Vcb->ReferenceCount++;
if (!FlagOn(be32_to_cpu(Fcb->romfs_inode->next), ROMFH_DIR))
{
Fcb->CommonFCBHeader.IsFastIoPossible = FastIoIsPossible;
}
IrpSp->FileObject->FsContext = (void*) Fcb;
IrpSp->FileObject->FsContext2 = (void*) Ccb;
IrpSp->FileObject->PrivateCacheMap = NULL;
IrpSp->FileObject->SectionObjectPointer = &(Fcb->SectionObject);
IrpSp->FileObject->Vpb = Vcb->Vpb;
if (Fcb->OpenHandleCount == 1)
{
IoSetShareAccess(
IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
IrpSp->Parameters.Create.ShareAccess,
IrpSp->FileObject,
&Fcb->ShareAccess
);
}
else
{
IoUpdateShareAccess(IrpSp->FileObject, &Fcb->ShareAccess);
}
Irp->IoStatus.Information = FILE_OPENED;
Status = STATUS_SUCCESS;
KdPrint((
DRIVER_NAME ": %s OpenHandleCount: %u ReferenceCount: %u\n",
Fcb->AnsiFileName.Buffer,
Fcb->OpenHandleCount,
Fcb->ReferenceCount
));
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
}
if (!NT_SUCCESS(Status) && Inode)
{
FsdFreePool(Inode);
}
if (!AbnormalTermination())
{
IrpContext->Irp->IoStatus.Status = Status;
FsdCompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
);
FsdFreeIrpContext(IrpContext);
if (Vcb &&
FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING) &&
!Vcb->ReferenceCount
)
{
FsdFreeVcb(Vcb);
}
}
}
return Status;
}
NTSTATUS
FsdLookupFileName (
IN PFSD_VCB Vcb,
IN PUNICODE_STRING FullFileName,
IN OUT PULONG Index,
IN OUT struct romfs_inode* Inode
)
{
UNICODE_STRING FileName;
if (FullFileName->Length == 0)
{
*Index = 0;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
if (FullFileName->Length == sizeof(WCHAR) && FullFileName->Buffer[0] == L'\\')
{
RtlCopyMemory(
Inode,
Vcb->root_inode,
sizeof(struct romfs_inode) + ROMFS_MAXFN
);
*Index = Vcb->root_inode_number;
return STATUS_SUCCESS;
}
FileName = *FullFileName;
FileName.Buffer++;
FileName.Length -= sizeof(WCHAR);
return FsdLookupFileNameInDir(
Vcb,
Vcb->root_inode_number,
&FileName,
Index,
Inode
);
}
NTSTATUS
FsdLookupFileNameInDir (
IN PFSD_VCB Vcb,
IN ULONG DirIndex,
IN PUNICODE_STRING FileName,
IN OUT PULONG Index,
IN OUT struct romfs_inode* Inode
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG FileIndex;
USHORT InodeFileNameLength;
UNICODE_STRING InodeFileName;
UNICODE_STRING slash_string;
InodeFileName.Buffer = NULL;
__try
{
FileIndex = DirIndex;
if (!(be32_to_cpu(FileIndex) & ROMFH_MASK))
{
Status = STATUS_NO_SUCH_FILE;
__leave;
}
while ((be32_to_cpu(FileIndex) & ROMFH_MASK))
{
Status = FsdReadInodeByIndex(
Vcb->TargetDeviceObject,
FileIndex,
Inode
);
if (!NT_SUCCESS(Status))
{
Status = STATUS_NO_SUCH_FILE;
__leave;
}
InodeFileNameLength = (USHORT) strnlen(Inode->name, ROMFS_MAXFN);
InodeFileName.Length =
InodeFileName.MaximumLength =
InodeFileNameLength * 2;
InodeFileName.Buffer = FsdAllocatePool(
NonPagedPool,
InodeFileName.MaximumLength,
'1rCR'
);
FsdCharToWchar(
InodeFileName.Buffer,
Inode->name,
InodeFileNameLength
);
if (!RtlCompareUnicodeString(
FileName,
&InodeFileName,
TRUE
))
{
*Index = FileIndex;
Status = STATUS_SUCCESS;
__leave;
}
if (InodeFileName.Buffer != NULL)
{
FsdFreePool(InodeFileName.Buffer);
InodeFileName.Buffer = NULL;
}
FileIndex = Inode->next;
}
Status = STATUS_NO_SUCH_FILE;
}
__finally
{
if (InodeFileName.Buffer != NULL)
{
FsdFreePool(InodeFileName.Buffer);
}
}
return Status;
}
PFSD_FCB
FsdLookupFcbByFileName (
IN PFSD_VCB Vcb,
IN PUNICODE_STRING FullFileName
)
{
PLIST_ENTRY ListEntry;
PFSD_FCB Fcb;
ListEntry = Vcb->FcbList.Flink;
while (ListEntry != &Vcb->FcbList)
{
Fcb = CONTAINING_RECORD(ListEntry, FSD_FCB, Next);
if (!RtlCompareUnicodeString(
&Fcb->FileName,
FullFileName,
TRUE
))
{
KdPrint((
DRIVER_NAME ": Found an allocated FCB for %s\n",
Fcb->AnsiFileName.Buffer
));
return Fcb;
}
ListEntry = ListEntry->Flink;
}
return NULL;
}
#pragma code_seg() // end FSD_PAGED_CODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -