/* Increment counters */
Dcb->OpenCount++;
+ Dcb->UncleanCount++;
Vcb->OpenFileCount++;
+ if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
/* Set success statuses */
Iosb.Status = STATUS_SUCCESS;
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
// TODO: Actually truncate the file
- DPRINT1("TODO: Actually truncate the file with a fullfat handle %x\n", Fcb->FatHandle);
+ DPRINT1("TODO: Actually truncate file '%wZ' with a fullfat handle %x\n", &Fcb->FullFileName, Fcb->FatHandle);
/* Release the paging resource */
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
Fcb,
FatCreateCcb());
+ /* Increase counters */
+ Fcb->UncleanCount++;
+ Fcb->OpenCount++;
+ Vcb->OpenFileCount++;
+ if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
+
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = FILE_OPENED;
PFCB Fcb;
NTSTATUS Status;
FF_FILE *FileHandle;
+ FF_ERROR FfError;
/* Check for create file option and fail */
if (CreateDisposition == FILE_CREATE)
}
/* Open the file with FullFAT */
- FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, NULL);
+ FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &FfError);
if (!FileHandle)
{
+ DPRINT1("Failed to open file '%s', error %ld\n", AnsiName.Buffer, FfError);
Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
return Iosb;
}
+ DPRINT1("Succeeded opening file '%s'\n", AnsiName.Buffer);
/* Create a new FCB for this file */
Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
// TODO: Check if overwrite is needed
- // This is usual file open branch, without overwriting!
+ // TODO: This is usual file open branch, without overwriting!
/* Set context and section object pointers */
FatSetFileObject(FileObject,
UserFileOpen,
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = FILE_OPENED;
+
+ /* Increase counters */
+ Fcb->UncleanCount++;
+ Fcb->OpenCount++;
+ if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;
+ if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
+
return Iosb;
}
// and opened handles count is not 0
//if (!FlagOn(ShareAccess, FILE_SHARE_READ)
- DPRINT1("Exclusive voume open\n");
+ DPRINT1("Exclusive volume open\n");
// TODO: Flush the volume
VolumeFlushed = TRUE;
/* Increase direct open count */
Vcb->DirectOpenCount++;
Vcb->OpenFileCount++;
+ if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
/* Set no buffering flag */
FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
PIO_STACK_LOCATION IrpSp;
- BOOLEAN EndBackslash = FALSE, OpenedAsDos;
+ BOOLEAN EndBackslash = FALSE, OpenedAsDos, FirstRun = TRUE;
UNICODE_STRING RemainingPart, FirstName, NextName, FileNameUpcased;
OEM_STRING AnsiFirstName;
FF_ERROR FfError;
if (RelatedFO)
FileObject->Vpb = RelatedFO->Vpb;
+ /* Reject open by id */
+ if (Options & FILE_OPEN_BY_FILE_ID)
+ {
+ FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
+ return STATUS_INVALID_PARAMETER;
+ }
+
/* Prepare file attributes mask */
FileAttributes &= (FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_HIDDEN |
DPRINT1("This volume is locked\n");
Status = STATUS_ACCESS_DENIED;
+ /* Set volume dismount status */
+ if (Vcb->Condition != VcbGood)
+ Status = STATUS_VOLUME_DISMOUNTED;
+
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
+ FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
- // TODO: Check if the volume is write protected and disallow DELETE_ON_CLOSE
+ /* Check if the volume is write protected and disallow DELETE_ON_CLOSE */
+ if (DeleteOnClose & FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
+ {
+ ASSERT(FALSE);
+ return STATUS_NOT_IMPLEMENTED;
+ }
// TODO: Make sure EAs aren't supported on FAT32
{
DPRINT1("Invalid file object!\n");
+ Status = STATUS_OBJECT_PATH_NOT_FOUND;
+
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
- return STATUS_OBJECT_PATH_NOT_FOUND;
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
}
/* File path must be relative */
if (FileName.Length != 0 &&
FileName.Buffer[0] == L'\\')
{
+ Status = STATUS_OBJECT_NAME_INVALID;
+
/* The name is absolute, fail */
FatReleaseVcb(IrpContext, Vcb);
- return STATUS_OBJECT_NAME_INVALID;
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
}
/* Make sure volume is the same */
/* Set parent DCB */
ParentDcb = RelatedDcb;
- DPRINT1("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
+ DPRINT("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
}
else
{
if (NonDirectoryFile)
{
DPRINT1("Trying to open root dir as a file\n");
+ Status = STATUS_FILE_IS_A_DIRECTORY;
+
+ /* Cleanup and return */
+ FatReleaseVcb(IrpContext, Vcb);
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
+ }
+
+ /* Check for target directory on a root dir */
+ if (OpenTargetDirectory)
+ {
+ Status = STATUS_INVALID_PARAMETER;
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
- return STATUS_FILE_IS_A_DIRECTORY;
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
}
/* Check delete on close on a root dir */
if (DeleteOnClose)
{
+ Status = STATUS_CANNOT_DELETE;
+
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
- return STATUS_CANNOT_DELETE;
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
}
/* Call root directory open routine */
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
else
}
}
+ /* Treat page file in a special way */
+ if (IsPagingFile)
+ {
+ UNIMPLEMENTED;
+ // FIXME: System file too
+ }
+
+ /* Make sure there is no pending delete on a higher-level FCB */
+ if (Fcb->State & FCB_STATE_DELETE_ON_CLOSE)
+ {
+ Iosb.Status = STATUS_DELETE_PENDING;
+
+ /* Cleanup and return */
+ FatReleaseVcb(IrpContext, Vcb);
+
+ /* Complete the request */
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+
+ return Iosb.Status;
+ }
+
/* We have a valid FCB now */
if (!RemainingPart.Length)
{
ParentDcb = Fcb;
while (TRUE)
{
- FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart);
-
- /* Check for validity */
- if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
- (NextName.Length > 255 * sizeof(WCHAR)))
+ if (FirstRun)
{
- /* The name is invalid */
- DPRINT1("Invalid name found\n");
- Iosb.Status = STATUS_OBJECT_NAME_INVALID;
- ASSERT(FALSE);
+ RemainingPart = NextName;
+ if (AnsiFirstName.Length)
+ Status = STATUS_SUCCESS;
+ else
+ Status = STATUS_UNMAPPABLE_CHARACTER;
}
+ else
+ {
+ FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart);
+
+ /* Check for validity */
+ if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
+ (NextName.Length > 255 * sizeof(WCHAR)))
+ {
+ /* The name is invalid */
+ DPRINT1("Invalid name found\n");
+ Iosb.Status = STATUS_OBJECT_NAME_INVALID;
+ ASSERT(FALSE);
+ }
- /* Convert the name to ANSI */
- AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
- AnsiFirstName.Length = 0;
- AnsiFirstName.MaximumLength = FirstName.Length;
- Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
+ /* Convert the name to ANSI */
+ AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
+ AnsiFirstName.Length = 0;
+ AnsiFirstName.MaximumLength = FirstName.Length;
+ Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
+ }
if (!NT_SUCCESS(Status))
{
}
/* Check, if path is a directory or a file */
- if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR)
+ if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR ||
+ FfError == FF_ERR_NONE)
{
- if (NonDirectoryFile)
+ if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR)
{
- DPRINT1("Can't open dir as a file\n");
+ if (NonDirectoryFile)
+ {
+ DPRINT1("Can't open dir as a file\n");
+
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
+
+ /* Complete the request */
+ Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+ return Iosb.Status;
+ }
+
+ /* Open this directory */
+ Iosb = FatiOpenExistingDir(IrpContext,
+ FileObject,
+ Vcb,
+ ParentDcb,
+ DesiredAccess,
+ ShareAccess,
+ AllocationSize,
+ EaBuffer,
+ EaLength,
+ FileAttributes,
+ CreateDisposition,
+ DeleteOnClose);
+
+ Irp->IoStatus.Information = Iosb.Information;
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
- Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+
return Iosb.Status;
}
+ else
+ {
+ /* This is opening an existing file */
+ if (OpenDirectory)
+ {
+ /* But caller wanted a dir */
+ Status = STATUS_NOT_A_DIRECTORY;
- /* Open this directory */
- Iosb = FatiOpenExistingDir(IrpContext,
- FileObject,
- Vcb,
- ParentDcb,
- DesiredAccess,
- ShareAccess,
- AllocationSize,
- EaBuffer,
- EaLength,
- FileAttributes,
- CreateDisposition,
- DeleteOnClose);
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
- Irp->IoStatus.Information = Iosb.Information;
+ /* Complete the request */
+ FatCompleteRequest(IrpContext, Irp, Status);
- /* Unlock VCB */
- FatReleaseVcb(IrpContext, Vcb);
+ return Status;
+ }
- /* Complete the request */
- FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+ /* If end backslash here, then it's definately not permitted,
+ since we're opening files here */
+ if (EndBackslash)
+ {
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
- return Iosb.Status;
- }
+ /* Complete the request */
+ Iosb.Status = STATUS_OBJECT_NAME_INVALID;
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+ return Iosb.Status;
+ }
- /* If end backslash here, then it's definately not permitted,
- since we're opening files here */
- if (EndBackslash)
- {
- /* Unlock VCB */
- FatReleaseVcb(IrpContext, Vcb);
+ /* Try to open the file */
+ Iosb = FatiOpenExistingFile(IrpContext,
+ FileObject,
+ Vcb,
+ ParentDcb,
+ DesiredAccess,
+ ShareAccess,
+ AllocationSize,
+ EaBuffer,
+ EaLength,
+ FileAttributes,
+ CreateDisposition,
+ FALSE,
+ DeleteOnClose,
+ OpenedAsDos);
+
+ /* In case of success set cache supported flag */
+ if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
+ {
+ SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
+ }
- /* Complete the request */
- Iosb.Status = STATUS_OBJECT_NAME_INVALID;
- FatCompleteRequest(IrpContext, Irp, Iosb.Status);
- return Iosb.Status;
+ Irp->IoStatus.Information = Iosb.Information;
+
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
+
+ /* Complete the request */
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+
+ return Iosb.Status;
+ }
}
- /* Try to open the file */
- Iosb = FatiOpenExistingFile(IrpContext,
- FileObject,
- Vcb,
- ParentDcb,
- DesiredAccess,
- ShareAccess,
- AllocationSize,
- EaBuffer,
- EaLength,
- FileAttributes,
- CreateDisposition,
- FALSE,
- DeleteOnClose,
- OpenedAsDos);
-
- Irp->IoStatus.Information = Iosb.Information;
-
- /* Unlock VCB */
- FatReleaseVcb(IrpContext, Vcb);
-
- /* Complete the request */
- FatCompleteRequest(IrpContext, Irp, Iosb.Status);
-
- return Iosb.Status;
+ /* We come here only in the case when a new file is created */
+ ASSERT(FALSE);
}
NTSTATUS