*/
/*
* PROJECT: ReactOS kernel
- * FILE: drivers/fs/vfat/create.c
+ * FILE: drivers/filesystems/fastfat/create.c
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES *****************************************************************/
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
- if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
+ if (BooleanFlagOn(pEntry->lCase, VFAT_CASE_LOWER_BASE))
{
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
}
StringA.Length++);
StringA.MaximumLength = StringA.Length;
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
- if (pEntry->lCase & VFAT_CASE_LOWER_EXT)
+ if (BooleanFlagOn(pEntry->lCase, VFAT_CASE_LOWER_EXT))
{
RtlDowncaseUnicodeString(NameU, NameU, FALSE);
}
DPRINT("'%wZ'\n", NameU);
}
-/*
- * FUNCTION: Read the volume label
- */
-NTSTATUS
-ReadVolumeLabel(
- PDEVICE_EXTENSION DeviceExt,
- PVPB Vpb)
-{
- PVOID Context = NULL;
- ULONG DirIndex = 0;
- PDIR_ENTRY Entry;
- PVFATFCB pFcb;
- LARGE_INTEGER FileOffset;
- UNICODE_STRING NameU;
- ULONG SizeDirEntry;
- ULONG EntriesPerPage;
- OEM_STRING StringO;
-
- NameU.Buffer = Vpb->VolumeLabel;
- NameU.Length = 0;
- NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
- *(Vpb->VolumeLabel) = 0;
- Vpb->VolumeLabelLength = 0;
-
- if (DeviceExt->Flags & VCB_IS_FATX)
- {
- SizeDirEntry = sizeof(FATX_DIR_ENTRY);
- EntriesPerPage = FATX_ENTRIES_PER_PAGE;
- }
- else
- {
- SizeDirEntry = sizeof(FAT_DIR_ENTRY);
- EntriesPerPage = FAT_ENTRIES_PER_PAGE;
- }
-
- ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
- pFcb = vfatOpenRootFCB(DeviceExt);
- ExReleaseResourceLite(&DeviceExt->DirResource);
-
- FileOffset.QuadPart = 0;
- if (CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
- {
- while (TRUE)
- {
- if (ENTRY_VOLUME(DeviceExt, Entry))
- {
- /* copy volume label */
- if (DeviceExt->Flags & VCB_IS_FATX)
- {
- StringO.Buffer = (PCHAR)Entry->FatX.Filename;
- StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
- RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
- }
- else
- {
- vfat8Dot3ToString(&Entry->Fat, &NameU);
- }
- Vpb->VolumeLabelLength = NameU.Length;
- break;
- }
- if (ENTRY_END(DeviceExt, Entry))
- {
- break;
- }
- DirIndex++;
- Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
- if ((DirIndex % EntriesPerPage) == 0)
- {
- CcUnpinData(Context);
- FileOffset.u.LowPart += PAGE_SIZE;
- if (!CcMapData(pFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
- {
- Context = NULL;
- break;
- }
- }
- }
- if (Context)
- {
- CcUnpinData(Context);
- }
- }
- ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE);
- vfatReleaseFCB(DeviceExt, pFcb);
- ExReleaseResourceLite(&DeviceExt->DirResource);
-
- return STATUS_SUCCESS;
-}
-
/*
* FUNCTION: Find a file
*/
UNICODE_STRING PathNameU;
UNICODE_STRING FileToFindUpcase;
BOOLEAN WildCard;
+ BOOLEAN IsFatX = vfatVolumeIsFatX(DeviceExt);
DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
Parent, FileToFindU, DirContext->DirIndex);
if (rcFcb)
{
ULONG startIndex = rcFcb->startIndex;
- if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent))
+ if (IsFatX && !vfatFCBIsRoot(Parent))
{
startIndex += 2;
}
while (TRUE)
{
- Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
+ Status = VfatGetNextDirEntry(DeviceExt, &Context, &Page, Parent, DirContext, First);
First = FALSE;
if (Status == STATUS_NO_MORE_ENTRIES)
{
break;
}
- if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry))
+ if (ENTRY_VOLUME(IsFatX, &DirContext->DirEntry))
{
DirContext->DirIndex++;
continue;
}
+ if (DirContext->LongNameU.Length == 0 ||
+ DirContext->ShortNameU.Length == 0)
+ {
+ DPRINT1("WARNING: File system corruption detected. You may need to run a disk repair utility.\n");
+ if (VfatGlobalData->Flags & VFAT_BREAK_ON_CORRUPTION)
+ {
+ ASSERT(DirContext->LongNameU.Length != 0 &&
+ DirContext->ShortNameU.Length != 0);
+ }
+ DirContext->DirIndex++;
+ continue;
+ }
if (WildCard)
{
Found = FsRtlIsNameInExpression(&FileToFindUpcase, &DirContext->LongNameU, TRUE, NULL) ||
PUNICODE_STRING PathNameU,
PFILE_OBJECT FileObject,
ULONG RequestedDisposition,
+ ULONG RequestedOptions,
PVFATFCB *ParentFcb)
{
PVFATFCB Fcb;
DPRINT("'%wZ'\n", &FileObject->RelatedFileObject->FileName);
*ParentFcb = FileObject->RelatedFileObject->FsContext;
- (*ParentFcb)->RefCount++;
}
else
{
if (*ParentFcb)
{
- (*ParentFcb)->RefCount++;
+ vfatGrabFCB(DeviceExt, *ParentFcb);
}
/* try first to find an existing FCB in memory */
DPRINT ("Could not make a new FCB, status: %x\n", Status);
return Status;
}
- if (Fcb->Flags & FCB_DELETE_PENDING)
+
+ /* Fail, if we try to overwrite an existing directory */
+ if ((!BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) && vfatFCBIsDirectory(Fcb)) &&
+ (RequestedDisposition == FILE_OVERWRITE ||
+ RequestedDisposition == FILE_OVERWRITE_IF ||
+ RequestedDisposition == FILE_SUPERSEDE))
+ {
+ vfatReleaseFCB(DeviceExt, Fcb);
+ return STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ if (BooleanFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
vfatReleaseFCB(DeviceExt, Fcb);
return STATUS_DELETE_PENDING;
}
/* Fail, if we try to overwrite a read-only file */
- if ((*Fcb->Attributes & FILE_ATTRIBUTE_READONLY) &&
- (RequestedDisposition == FILE_OVERWRITE))
+ if (vfatFCBIsReadOnly(Fcb) &&
+ (RequestedDisposition == FILE_OVERWRITE ||
+ RequestedDisposition == FILE_OVERWRITE_IF))
{
vfatReleaseFCB(DeviceExt, Fcb);
return STATUS_ACCESS_DENIED;
}
+ if (vfatFCBIsReadOnly(Fcb) &&
+ (RequestedOptions & FILE_DELETE_ON_CLOSE))
+ {
+ vfatReleaseFCB(DeviceExt, Fcb);
+ return STATUS_CANNOT_DELETE;
+ }
+
+ if ((vfatFCBIsRoot(Fcb) ||
+ (Fcb->LongNameU.Length == sizeof(WCHAR) && Fcb->LongNameU.Buffer[0] == L'.') ||
+ (Fcb->LongNameU.Length == 2 * sizeof(WCHAR) && Fcb->LongNameU.Buffer[0] == L'.' && Fcb->LongNameU.Buffer[1] == L'.')) &&
+ BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
+ {
+ // we cannot delete a '.', '..' or the root directory
+ vfatReleaseFCB(DeviceExt, Fcb);
+ return STATUS_CANNOT_DELETE;
+ }
+
DPRINT("Attaching FCB to fileObject\n");
Status = vfatAttachFCBToFileObject(DeviceExt, Fcb, FileObject);
if (!NT_SUCCESS(Status))
ULONG RequestedDisposition, RequestedOptions;
PVFATFCB pFcb = NULL;
PVFATFCB ParentFcb = NULL;
+ PVFATCCB pCcb = NULL;
PWCHAR c, last;
- BOOLEAN PagingFileCreate = FALSE;
+ BOOLEAN PagingFileCreate;
BOOLEAN Dots;
+ BOOLEAN OpenTargetDir;
+ BOOLEAN TrailingBackslash;
UNICODE_STRING FileNameU;
UNICODE_STRING PathNameU;
ULONG Attributes;
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;
+ PagingFileCreate = BooleanFlagOn(Stack->Flags, SL_OPEN_PAGING_FILE);
+ OpenTargetDir = BooleanFlagOn(Stack->Flags, SL_OPEN_TARGET_DIRECTORY);
+
FileObject = Stack->FileObject;
DeviceExt = DeviceObject->DeviceExtension;
+ if (BooleanFlagOn(Stack->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID))
+ {
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
/* Check their validity. */
- if (RequestedOptions & FILE_DIRECTORY_FILE &&
+ if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
RequestedDisposition == FILE_SUPERSEDE)
{
return STATUS_INVALID_PARAMETER;
}
- if (RequestedOptions & FILE_DIRECTORY_FILE &&
- RequestedOptions & FILE_NON_DIRECTORY_FILE)
+ if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
+ BooleanFlagOn(RequestedOptions, FILE_NON_DIRECTORY_FILE))
{
return STATUS_INVALID_PARAMETER;
}
+ /* Deny create if the volume is locked */
+ if (BooleanFlagOn(DeviceExt->Flags, VCB_VOLUME_LOCKED))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
/* This a open operation for the volume itself */
if (FileObject->FileName.Length == 0 &&
- (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
+ (FileObject->RelatedFileObject == NULL ||
+ FileObject->RelatedFileObject->FsContext2 != NULL ||
+ FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb))
{
+ DPRINT("Volume opening\n");
+
if (RequestedDisposition != FILE_OPEN &&
RequestedDisposition != FILE_OPEN_IF)
{
return STATUS_ACCESS_DENIED;
}
-#if 0
- /* In spite of what is shown in WDK, it seems that Windows FAT driver doesn't perform that test */
- if (RequestedOptions & FILE_DIRECTORY_FILE)
+
+ if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
+ (FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 == NULL || FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb))
{
return STATUS_NOT_A_DIRECTORY;
}
-#endif
+
+ if (OpenTargetDir)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
+ {
+ return STATUS_CANNOT_DELETE;
+ }
+
+ vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
pFcb = DeviceExt->VolumeFcb;
+
+ if (pFcb->OpenHandleCount == 0)
+ {
+ IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess);
+ }
+ else
+ {
+ Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return Status;
+ }
+ }
+
vfatAttachFCBToFileObject(DeviceExt, pFcb, FileObject);
- pFcb->RefCount++;
+ DeviceExt->OpenHandleCount++;
+ pFcb->OpenHandleCount++;
+ vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
Irp->IoStatus.Information = FILE_OPENED;
return STATUS_SUCCESS;
}
- /* Check for illegal characters and illegale dot sequences in the file name */
+ if (FileObject->RelatedFileObject != NULL &&
+ FileObject->RelatedFileObject->FsContext == DeviceExt->VolumeFcb)
+ {
+ ASSERT(FileObject->FileName.Length != 0);
+ return STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ /* Check for illegal characters and illegal 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)
{
{
return STATUS_OBJECT_NAME_INVALID;
}
+ if (*c == L'\\' && (c - 1) > PathNameU.Buffer &&
+ *(c - 1) == L'\\')
+ {
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+
last = c - 1;
Dots = TRUE;
}
}
}
+ /* Check if we try to open target directory of root dir */
+ if (OpenTargetDir && FileObject->RelatedFileObject == NULL && PathNameU.Length == sizeof(WCHAR) &&
+ PathNameU.Buffer[0] == L'\\')
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
if (FileObject->RelatedFileObject && PathNameU.Length >= sizeof(WCHAR) && PathNameU.Buffer[0] == L'\\')
{
return STATUS_OBJECT_NAME_INVALID;
}
+ TrailingBackslash = FALSE;
if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
{
PathNameU.Length -= sizeof(WCHAR);
+ TrailingBackslash = TRUE;
+ }
+
+ if (PathNameU.Length > sizeof(WCHAR) && PathNameU.Buffer[PathNameU.Length/sizeof(WCHAR)-1] == L'\\')
+ {
+ return STATUS_OBJECT_NAME_INVALID;
}
/* Try opening the file. */
- Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, &ParentFcb);
+ if (!OpenTargetDir)
+ {
+ vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
+
+ Status = VfatOpenFile(DeviceExt, &PathNameU, FileObject, RequestedDisposition, RequestedOptions, &ParentFcb);
+ }
+ else
+ {
+ PVFATFCB TargetFcb;
+ LONG idx, FileNameLen;
+
+ vfatAddToStat(DeviceExt, Fat.CreateHits, 1);
+
+ ParentFcb = (FileObject->RelatedFileObject != NULL) ? FileObject->RelatedFileObject->FsContext : NULL;
+ if (ParentFcb)
+ {
+ vfatGrabFCB(DeviceExt, ParentFcb);
+ }
+
+ Status = vfatGetFCBForFile(DeviceExt, &ParentFcb, &TargetFcb, &PathNameU);
+ if (NT_SUCCESS(Status))
+ {
+ vfatReleaseFCB(DeviceExt, TargetFcb);
+ Irp->IoStatus.Information = FILE_EXISTS;
+ }
+ else
+ {
+ Irp->IoStatus.Information = FILE_DOES_NOT_EXIST;
+ }
+
+ idx = FileObject->FileName.Length / sizeof(WCHAR) - 1;
+
+ /* Skip trailing \ - if any */
+ if (PathNameU.Buffer[idx] == L'\\')
+ {
+ --idx;
+ PathNameU.Length -= sizeof(WCHAR);
+ }
+
+ /* Get file name */
+ while (idx >= 0 && PathNameU.Buffer[idx] != L'\\')
+ {
+ --idx;
+ }
+
+ if (idx > 0 || PathNameU.Buffer[0] == L'\\')
+ {
+ /* We don't want to include / in the name */
+ FileNameLen = PathNameU.Length - ((idx + 1) * sizeof(WCHAR));
+
+ /* Update FO just to keep file name */
+ /* Skip first slash */
+ ++idx;
+ FileObject->FileName.Length = FileNameLen;
+ RtlMoveMemory(&PathNameU.Buffer[0], &PathNameU.Buffer[idx], FileObject->FileName.Length);
+#if 0
+ /* Terminate the string at the last backslash */
+ PathNameU.Buffer[idx + 1] = UNICODE_NULL;
+ PathNameU.Length = (idx + 1) * sizeof(WCHAR);
+ PathNameU.MaximumLength = PathNameU.Length + sizeof(WCHAR);
+
+ /* Update the file object as well */
+ FileObject->FileName.Length = PathNameU.Length;
+ FileObject->FileName.MaximumLength = PathNameU.MaximumLength;
+#endif
+ }
+ else
+ {
+ /* This is a relative open and we have only the filename, so open the parent directory
+ * It is in RelatedFileObject
+ */
+ ASSERT(FileObject->RelatedFileObject != NULL);
+
+ /* No need to modify the FO, it already has the name */
+ }
+
+ /* We're done with opening! */
+ if (ParentFcb != NULL)
+ {
+ Status = vfatAttachFCBToFileObject(DeviceExt, ParentFcb, FileObject);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ pFcb = FileObject->FsContext;
+ ASSERT(pFcb == ParentFcb);
+
+ if (pFcb->OpenHandleCount == 0)
+ {
+ IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess);
+ }
+ else
+ {
+ Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
+ Stack->Parameters.Create.ShareAccess,
+ FileObject,
+ &pFcb->FCBShareAccess,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return Status;
+ }
+ }
+
+ pCcb = FileObject->FsContext2;
+ if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
+ {
+ pCcb->Flags |= CCB_DELETE_ON_CLOSE;
+ }
+
+ pFcb->OpenHandleCount++;
+ DeviceExt->OpenHandleCount++;
+ }
+ else if (ParentFcb != NULL)
+ {
+ vfatReleaseFCB(DeviceExt, ParentFcb);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
+ }
+ else
+ {
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ }
+
+ return Status;
+ }
/*
* If the directory containing the file to open doesn't exist then
*/
if (Status == STATUS_OBJECT_PATH_NOT_FOUND ||
Status == STATUS_INVALID_PARAMETER ||
- Status == STATUS_DELETE_PENDING)
+ Status == STATUS_DELETE_PENDING ||
+ Status == STATUS_ACCESS_DENIED ||
+ Status == STATUS_OBJECT_NAME_COLLISION)
{
if (ParentFcb)
{
vfatReleaseFCB(DeviceExt, ParentFcb);
}
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
if (!NT_SUCCESS(Status) && ParentFcb == NULL)
{
- DPRINT1("VfatOpenFile faild for '%wZ', status %x\n", &PathNameU, Status);
+ DPRINT1("VfatOpenFile failed for '%wZ', status %x\n", &PathNameU, Status);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
+ Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
+
/* If the file open failed then create the required file */
if (!NT_SUCCESS (Status))
{
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
- Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
- if (!(RequestedOptions & FILE_DIRECTORY_FILE))
+ if (!BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE))
+ {
+ if (TrailingBackslash)
+ {
+ vfatReleaseFCB(DeviceExt, ParentFcb);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return STATUS_OBJECT_NAME_INVALID;
+ }
Attributes |= FILE_ATTRIBUTE_ARCHIVE;
+ }
vfatSplitPathName(&PathNameU, NULL, &FileNameU);
Status = VfatAddEntry(DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
- (UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
+ (UCHAR)FlagOn(Attributes, FILE_ATTRIBUTE_VALID_FLAGS), NULL);
vfatReleaseFCB(DeviceExt, ParentFcb);
if (NT_SUCCESS(Status))
{
if (!NT_SUCCESS(Status))
{
vfatReleaseFCB(DeviceExt, pFcb);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
}
else
{
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
}
else
{
- if (ParentFcb)
- {
- vfatReleaseFCB(DeviceExt, ParentFcb);
- }
+ vfatReleaseFCB(DeviceExt, ParentFcb);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
}
vfatReleaseFCB(DeviceExt, ParentFcb);
}
+ pFcb = FileObject->FsContext;
+
/* Otherwise fail if the caller wanted to create a new file */
if (RequestedDisposition == FILE_CREATE)
{
- Irp->IoStatus.Information = FILE_EXISTS;
VfatCloseFile(DeviceExt, FileObject);
+ if (TrailingBackslash && !vfatFCBIsDirectory(pFcb))
+ {
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+ Irp->IoStatus.Information = FILE_EXISTS;
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return STATUS_OBJECT_NAME_COLLISION;
}
- pFcb = FileObject->FsContext;
-
if (pFcb->OpenHandleCount != 0)
{
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
if (!NT_SUCCESS(Status))
{
VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
}
/*
* Check the file has the requested attributes
*/
- if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
- *pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
+ if (BooleanFlagOn(RequestedOptions, FILE_NON_DIRECTORY_FILE) &&
+ vfatFCBIsDirectory(pFcb))
{
VfatCloseFile (DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return STATUS_FILE_IS_A_DIRECTORY;
}
- if (RequestedOptions & FILE_DIRECTORY_FILE &&
- !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
+ if (BooleanFlagOn(RequestedOptions, FILE_DIRECTORY_FILE) &&
+ !vfatFCBIsDirectory(pFcb))
{
VfatCloseFile (DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return STATUS_NOT_A_DIRECTORY;
}
+ if (TrailingBackslash && !vfatFCBIsDirectory(pFcb))
+ {
+ VfatCloseFile (DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return STATUS_OBJECT_NAME_INVALID;
+ }
#ifndef USE_ROS_CC_AND_FS
- if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
+ if (!vfatFCBIsDirectory(pFcb))
{
- if (Stack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA ||
+ if (BooleanFlagOn(Stack->Parameters.Create.SecurityContext->DesiredAccess, FILE_WRITE_DATA) ||
RequestedDisposition == FILE_OVERWRITE ||
- RequestedDisposition == FILE_OVERWRITE_IF)
+ RequestedDisposition == FILE_OVERWRITE_IF ||
+ (RequestedOptions & FILE_DELETE_ON_CLOSE))
{
if (!MmFlushImageSection(&pFcb->SectionObjectPointers, MmFlushForWrite))
{
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;
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE)) ? STATUS_CANNOT_DELETE
+ : STATUS_SHARING_VIOLATION;
}
}
}
*/
if (pFcb->RefCount > 1)
{
- if(!(pFcb->Flags & FCB_IS_PAGE_FILE))
+ if(!BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE))
{
VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return STATUS_INVALID_PARAMETER;
}
}
}
else
{
- if (pFcb->Flags & FCB_IS_PAGE_FILE)
+ if (BooleanFlagOn(pFcb->Flags, FCB_IS_PAGE_FILE))
{
VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return STATUS_INVALID_PARAMETER;
}
}
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
{
- if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
+ if ((BooleanFlagOn(*pFcb->Attributes, FILE_ATTRIBUTE_HIDDEN) && !BooleanFlagOn(Attributes, FILE_ATTRIBUTE_HIDDEN)) ||
+ (BooleanFlagOn(*pFcb->Attributes, FILE_ATTRIBUTE_SYSTEM) && !BooleanFlagOn(Attributes, FILE_ATTRIBUTE_SYSTEM)))
+ {
+ VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ if (!vfatFCBIsDirectory(pFcb))
{
- *pFcb->Attributes = Stack->Parameters.Create.FileAttributes & ~FILE_ATTRIBUTE_NORMAL;
+ *pFcb->Attributes = Attributes & ~FILE_ATTRIBUTE_NORMAL;
*pFcb->Attributes |= FILE_ATTRIBUTE_ARCHIVE;
- VfatUpdateEntry(pFcb);
+ VfatUpdateEntry(pFcb, vfatVolumeIsFatX(DeviceExt));
}
ExAcquireResourceExclusiveLite(&(pFcb->MainResource), TRUE);
if (!NT_SUCCESS (Status))
{
VfatCloseFile(DeviceExt, FileObject);
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
return Status;
}
}
&pFcb->FCBShareAccess);
}
+ pCcb = FileObject->FsContext2;
+ if (BooleanFlagOn(RequestedOptions, FILE_DELETE_ON_CLOSE))
+ {
+ pCcb->Flags |= CCB_DELETE_ON_CLOSE;
+ }
+
+ if (Irp->IoStatus.Information == FILE_CREATED)
+ {
+ FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
+ &(DeviceExt->NotifyList),
+ (PSTRING)&pFcb->PathNameU,
+ pFcb->PathNameU.Length - pFcb->LongNameU.Length,
+ NULL,
+ NULL,
+ (vfatFCBIsDirectory(pFcb) ?
+ FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
+ FILE_ACTION_ADDED,
+ NULL);
+ }
+
pFcb->OpenHandleCount++;
+ DeviceExt->OpenHandleCount++;
/* FIXME : test write access if requested */
+ /* FIXME: That is broken, we cannot reach this code path with failure */
+ ASSERT(NT_SUCCESS(Status));
+ if (NT_SUCCESS(Status))
+ {
+ vfatAddToStat(DeviceExt, Fat.SuccessfulCreates, 1);
+ }
+ else
+ {
+ vfatAddToStat(DeviceExt, Fat.FailedCreates, 1);
+ }
+
return Status;
}
/* 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);
+ IrpContext->PriorityBoost = IO_DISK_INCREMENT;
+
return STATUS_SUCCESS;
}
- if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
+ if (!BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))
{
- return(VfatQueueRequest(IrpContext));
+ return VfatMarkIrpContextForQueue(IrpContext);
}
IrpContext->Irp->IoStatus.Information = 0;
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);
+ if (NT_SUCCESS(Status))
+ IrpContext->PriorityBoost = IO_DISK_INCREMENT;
+
return Status;
}