create.c
来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 805 行 · 第 1/2 页
C
805 行
/* try first to find an existing FCB in memory */
DPRINT ("Checking for existing FCB in memory\n");
Status = vfatGetFCBForFile (DeviceExt, ParentFcb, &Fcb, PathNameU);
if (!NT_SUCCESS (Status))
{
DPRINT ("Could not make a new FCB, status: %x\n", Status);
return Status;
}
if (Fcb->Flags & FCB_DELETE_PENDING)
{
vfatReleaseFCB (DeviceExt, Fcb);
return STATUS_DELETE_PENDING;
}
DPRINT ("Attaching FCB to fileObject\n");
Status = vfatAttachFCBToFileObject (DeviceExt, Fcb, FileObject);
if (!NT_SUCCESS(Status))
{
vfatReleaseFCB (DeviceExt, Fcb);
}
return Status;
}
static NTSTATUS
VfatCreateFile ( PDEVICE_OBJECT DeviceObject, PIRP Irp )
/*
* FUNCTION: Create or open a file
*/
{
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION DeviceExt;
ULONG RequestedDisposition, RequestedOptions;
PVFATCCB pCcb;
PVFATFCB pFcb = NULL;
PVFATFCB ParentFcb = NULL;
PWCHAR c, last;
BOOLEAN PagingFileCreate = FALSE;
BOOLEAN Dots;
UNICODE_STRING FileNameU;
UNICODE_STRING PathNameU;
/* Unpack the various parameters. */
Stack = IoGetCurrentIrpStackLocation (Irp);
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
RequestedOptions =
Stack->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
PagingFileCreate = (Stack->Flags & SL_OPEN_PAGING_FILE) ? TRUE : FALSE;
FileObject = Stack->FileObject;
DeviceExt = DeviceObject->DeviceExtension;
/* Check their validity. */
if (RequestedOptions & FILE_DIRECTORY_FILE &&
RequestedDisposition == FILE_SUPERSEDE)
{
return(STATUS_INVALID_PARAMETER);
}
if (RequestedOptions & FILE_DIRECTORY_FILE &&
RequestedOptions & FILE_NON_DIRECTORY_FILE)
{
return(STATUS_INVALID_PARAMETER);
}
/* This a open operation for the volume itself */
if (FileObject->FileName.Length == 0 &&
FileObject->RelatedFileObject == NULL)
{
if (RequestedDisposition == FILE_CREATE ||
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
return(STATUS_ACCESS_DENIED);
}
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
return(STATUS_NOT_A_DIRECTORY);
}
pFcb = DeviceExt->VolumeFcb;
pCcb = ExAllocateFromNPagedLookasideList(&VfatGlobalData->CcbLookasideList);
if (pCcb == NULL)
{
return (STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(pCcb, sizeof(VFATCCB));
FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
FileObject->FsContext = pFcb;
FileObject->FsContext2 = pCcb;
pFcb->RefCount++;
Irp->IoStatus.Information = FILE_OPENED;
return(STATUS_SUCCESS);
}
/*
* Check for illegal characters and illegale dot sequences in the file name
*/
PathNameU = FileObject->FileName;
c = PathNameU.Buffer + PathNameU.Length / sizeof(WCHAR);
last = c - 1;
Dots = TRUE;
while (c-- > PathNameU.Buffer)
{
if (*c == L'\\' || c == PathNameU.Buffer)
{
if (Dots && last > c)
{
return(STATUS_OBJECT_NAME_INVALID);
}
last = c - 1;
Dots = TRUE;
}
else if (*c != L'.')
{
Dots = FALSE;
}
if (*c != '\\' && vfatIsLongIllegal(*c))
{
return(STATUS_OBJECT_NAME_INVALID);
}
}
if (FileObject->RelatedFileObject && PathNameU.Buffer[0] == L'\\')
{
return(STATUS_OBJECT_NAME_INVALID);
}
if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
{
PathNameU.Length -= sizeof(WCHAR);
}
/* Try opening the file. */
Status = VfatOpenFile (DeviceExt, &PathNameU, FileObject, &ParentFcb);
/*
* If the directory containing the file to open doesn't exist then
* fail immediately
*/
if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
Status == STATUS_INVALID_PARAMETER ||
Status == STATUS_DELETE_PENDING)
{
if (ParentFcb)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
}
return(Status);
}
if (!NT_SUCCESS(Status) && ParentFcb == NULL)
{
DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU, Status);
return Status;
}
/*
* If the file open failed then create the required file
*/
if (!NT_SUCCESS (Status))
{
if (RequestedDisposition == FILE_CREATE ||
RequestedDisposition == FILE_OPEN_IF ||
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
ULONG Attributes;
Attributes = Stack->Parameters.Create.FileAttributes;
vfatSplitPathName(&PathNameU, NULL, &FileNameU);
Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
vfatReleaseFCB (DeviceExt, ParentFcb);
if (NT_SUCCESS (Status))
{
Status = vfatAttachFCBToFileObject (DeviceExt, pFcb, FileObject);
if ( !NT_SUCCESS(Status) )
{
vfatReleaseFCB (DeviceExt, pFcb);
return Status;
}
Irp->IoStatus.Information = FILE_CREATED;
VfatSetAllocationSizeInformation(FileObject,
pFcb,
DeviceExt,
&Irp->Overlay.AllocationSize);
VfatSetExtendedAttributes(FileObject,
Irp->AssociatedIrp.SystemBuffer,
Stack->Parameters.Create.EaLength);
if (PagingFileCreate)
{
pFcb->Flags |= FCB_IS_PAGE_FILE;
}
}
else
{
return(Status);
}
}
else
{
if (ParentFcb)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
}
return(Status);
}
}
else
{
if (ParentFcb)
{
vfatReleaseFCB (DeviceExt, ParentFcb);
}
/* Otherwise fail if the caller wanted to create a new file */
if (RequestedDisposition == FILE_CREATE)
{
Irp->IoStatus.Information = FILE_EXISTS;
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_OBJECT_NAME_COLLISION);
}
pFcb = FileObject->FsContext;
if (pFcb->OpenHandleCount != 0)
{
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
Stack->Parameters.Create.ShareAccess,
FileObject,
&pFcb->FCBShareAccess,
FALSE);
if (!NT_SUCCESS(Status))
{
VfatCloseFile (DeviceExt, FileObject);
return(Status);
}
}
/*
* Check the file has the requested attributes
*/
if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
{
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_FILE_IS_A_DIRECTORY);
}
if (RequestedOptions & FILE_DIRECTORY_FILE &&
!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_NOT_A_DIRECTORY);
}
#ifndef USE_ROS_CC_AND_FS
if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA ||
RequestedDisposition == FILE_OVERWRITE ||
RequestedDisposition == FILE_OVERWRITE_IF)
{
if (!MmFlushImageSection(&pFcb->SectionObjectPointers, MmFlushForWrite))
{
DPRINT1("%wZ\n", &pFcb->PathNameU);
DPRINT1("%d %d %d\n", Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA,
RequestedDisposition == FILE_OVERWRITE, RequestedDisposition == FILE_OVERWRITE_IF);
VfatCloseFile (DeviceExt, FileObject);
return STATUS_SHARING_VIOLATION;
}
}
}
#endif
if (PagingFileCreate)
{
/* FIXME:
* Do more checking for page files. It is possible,
* that the file was opened and closed previously
* as a normal cached file. In this case, the cache
* manager has referenced the fileobject and the fcb
* is held in memory. Try to remove the fileobject
* from cache manager and use the fcb.
*/
if (pFcb->RefCount > 1)
{
if(!(pFcb->Flags & FCB_IS_PAGE_FILE))
{
VfatCloseFile(DeviceExt, FileObject);
return(STATUS_INVALID_PARAMETER);
}
}
else
{
pFcb->Flags |= FCB_IS_PAGE_FILE;
}
}
else
{
if (pFcb->Flags & FCB_IS_PAGE_FILE)
{
VfatCloseFile(DeviceExt, FileObject);
return(STATUS_INVALID_PARAMETER);
}
}
if (RequestedDisposition == FILE_OVERWRITE ||
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
ExAcquireResourceExclusiveLite(&(pFcb->MainResource), TRUE);
Status = VfatSetAllocationSizeInformation (FileObject,
pFcb,
DeviceExt,
&Irp->Overlay.AllocationSize);
ExReleaseResourceLite(&(pFcb->MainResource));
if (!NT_SUCCESS (Status))
{
VfatCloseFile (DeviceExt, FileObject);
return(Status);
}
}
if (RequestedDisposition == FILE_SUPERSEDE)
{
Irp->IoStatus.Information = FILE_SUPERSEDED;
}
else if (RequestedDisposition == FILE_OVERWRITE ||
RequestedDisposition == FILE_OVERWRITE_IF)
{
Irp->IoStatus.Information = FILE_OVERWRITTEN;
}
else
{
Irp->IoStatus.Information = FILE_OPENED;
}
}
if (pFcb->OpenHandleCount == 0)
{
IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
Stack->Parameters.Create.ShareAccess,
FileObject,
&pFcb->FCBShareAccess);
}
else
{
IoUpdateShareAccess(
FileObject,
&pFcb->FCBShareAccess
);
}
pFcb->OpenHandleCount++;
/* FIXME : test write access if requested */
return(Status);
}
NTSTATUS
VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
/*
* FUNCTION: Create or open a file
*/
{
NTSTATUS Status;
ASSERT(IrpContext);
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
/* DeviceObject represents FileSystem instead of logical volume */
DPRINT ("FsdCreate called with file system\n");
IrpContext->Irp->IoStatus.Information = FILE_OPENED;
IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest (IrpContext->Irp, IO_DISK_INCREMENT);
VfatFreeIrpContext(IrpContext);
return(STATUS_SUCCESS);
}
if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
{
return(VfatQueueRequest (IrpContext));
}
IrpContext->Irp->IoStatus.Information = 0;
ExAcquireResourceExclusiveLite (&IrpContext->DeviceExt->DirResource, TRUE);
Status = VfatCreateFile (IrpContext->DeviceObject, IrpContext->Irp);
ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest (IrpContext->Irp,
(CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
VfatFreeIrpContext(IrpContext);
return(Status);
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?