return Iosb;
}
+FF_ERROR
+NTAPI
+FatiTryToOpen(IN PFILE_OBJECT FileObject,
+ IN PVCB Vcb)
+{
+ OEM_STRING AnsiName;
+ CHAR AnsiNameBuf[512];
+ FF_ERROR Error;
+ NTSTATUS Status;
+ FF_FILE *FileHandle;
+
+ /* Convert the name to ANSI */
+ AnsiName.Buffer = AnsiNameBuf;
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = sizeof(AnsiNameBuf);
+ RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
+ Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, &FileObject->FileName, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ ASSERT(FALSE);
+ }
+
+ /* Open the file with FullFAT */
+ FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, &Error);
+
+ /* Close the handle */
+ if (FileHandle) FF_Close(FileHandle);
+
+ /* Return status */
+ return Error;
+}
+
+IO_STATUS_BLOCK
+NTAPI
+FatiOpenExistingDir(IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN PVCB Vcb,
+ IN PFCB ParentDcb,
+ IN PACCESS_MASK DesiredAccess,
+ IN USHORT ShareAccess,
+ IN ULONG AllocationSize,
+ IN PFILE_FULL_EA_INFORMATION EaBuffer,
+ IN ULONG EaLength,
+ IN UCHAR FileAttributes,
+ IN ULONG CreateDisposition,
+ IN BOOLEAN DeleteOnClose)
+{
+ IO_STATUS_BLOCK Iosb = {{0}};
+ OEM_STRING AnsiName;
+ CHAR AnsiNameBuf[512];
+ PFCB Fcb;
+ NTSTATUS Status;
+ FF_FILE *FileHandle;
+
+ /* Only open is permitted */
+ if (CreateDisposition != FILE_OPEN &&
+ CreateDisposition != FILE_OPEN_IF)
+ {
+ Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
+ return Iosb;
+ }
+
+ // TODO: Check dir access
+
+ /* Convert the name to ANSI */
+ AnsiName.Buffer = AnsiNameBuf;
+ AnsiName.Length = 0;
+ AnsiName.MaximumLength = sizeof(AnsiNameBuf);
+ RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
+ Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, &FileObject->FileName, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ ASSERT(FALSE);
+ }
+
+ /* Open the dir with FullFAT */
+ FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_DIR, NULL);
+
+ if (!FileHandle)
+ {
+ Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
+ return Iosb;
+ }
+
+ /* Create a new DCB for this directory */
+ Fcb = FatCreateDcb(IrpContext, Vcb, ParentDcb, FileHandle);
+
+ /* Set share access */
+ IoSetShareAccess(*DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess);
+
+ /* Set context and section object pointers */
+ FatSetFileObject(FileObject,
+ UserDirectoryOpen,
+ Fcb,
+ FatCreateCcb());
+
+ Iosb.Status = STATUS_SUCCESS;
+ Iosb.Information = FILE_OPENED;
+
+ DPRINT1("Successfully opened dir %s\n", AnsiNameBuf);
+
+ return Iosb;
+}
+
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingFile(IN PFAT_IRP_CONTEXT IrpContext,
CHAR AnsiNameBuf[512];
PFCB Fcb;
NTSTATUS Status;
+ FF_FILE *FileHandle;
/* Check for create file option and fail */
if (CreateDisposition == FILE_CREATE)
// TODO: Check more params
- /* Create a new FCB for this file */
- Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb);
-
/* Convert the name to ANSI */
AnsiName.Buffer = AnsiNameBuf;
AnsiName.Length = 0;
}
/* Open the file with FullFAT */
- Fcb->FatHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, NULL);
+ FileHandle = FF_Open(Vcb->Ioman, AnsiName.Buffer, FF_MODE_READ, NULL);
+
+ if (!FileHandle)
+ {
+ Iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; // FIXME: A shortcut for now
+ return Iosb;
+ }
+
+ /* Create a new FCB for this file */
+ Fcb = FatCreateFcb(IrpContext, Vcb, ParentDcb, FileHandle);
// TODO: Check if overwrite is needed
return Iosb;
}
+IO_STATUS_BLOCK
+NTAPI
+FatiOpenVolume(IN PFAT_IRP_CONTEXT IrpContext,
+ IN PFILE_OBJECT FileObject,
+ IN PVCB Vcb,
+ IN PACCESS_MASK DesiredAccess,
+ IN USHORT ShareAccess,
+ IN ULONG CreateDisposition)
+{
+ PCCB Ccb;
+ IO_STATUS_BLOCK Iosb = {{0}};
+ BOOLEAN VolumeFlushed = FALSE;
+
+ /* Check parameters */
+ if (CreateDisposition != FILE_OPEN &&
+ CreateDisposition != FILE_OPEN_IF)
+ {
+ /* Deny access */
+ Iosb.Status = STATUS_ACCESS_DENIED;
+ }
+
+ /* Check if it's exclusive open */
+ if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) &&
+ !FlagOn(ShareAccess, FILE_SHARE_DELETE))
+ {
+ // TODO: Check if exclusive read access requested
+ // and opened handles count is not 0
+ //if (!FlagOn(ShareAccess, FILE_SHARE_READ)
+
+ DPRINT1("Exclusive voume open\n");
+
+ // TODO: Flush the volume
+ VolumeFlushed = TRUE;
+ }
+ else if (FlagOn(*DesiredAccess, FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA))
+ {
+ DPRINT1("Shared open\n");
+
+ // TODO: Flush the volume
+ VolumeFlushed = TRUE;
+ }
+
+ if (VolumeFlushed &&
+ !FlagOn(Vcb->State, VCB_STATE_MOUNTED_DIRTY) &&
+ FlagOn(Vcb->State, VCB_STATE_FLAG_DIRTY) &&
+ CcIsThereDirtyData(Vcb->Vpb))
+ {
+ UNIMPLEMENTED;
+ }
+
+ /* Set share access */
+ if (Vcb->DirectOpenCount > 0)
+ {
+ /* This volume has already been opened */
+ Iosb.Status = IoCheckShareAccess(*DesiredAccess,
+ ShareAccess,
+ FileObject,
+ &Vcb->ShareAccess,
+ TRUE);
+
+ if (!NT_SUCCESS(Iosb.Status))
+ {
+ ASSERT(FALSE);
+ }
+ }
+ else
+ {
+ /* This is the first time open */
+ IoSetShareAccess(*DesiredAccess,
+ ShareAccess,
+ FileObject,
+ &Vcb->ShareAccess);
+ }
+
+ /* Set file object pointers */
+ Ccb = FatCreateCcb(IrpContext);
+ FatSetFileObject(FileObject, UserVolumeOpen, Vcb, Ccb);
+ FileObject->SectionObjectPointer = &Vcb->SectionObjectPointers;
+
+ /* Increase direct open count */
+ Vcb->DirectOpenCount++;
+ Vcb->OpenFileCount++;
+
+ /* Set no buffering flag */
+ FileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
+
+ // TODO: User's access check
+
+ Iosb.Status = STATUS_SUCCESS;
+ Iosb.Information = FILE_OPENED;
+
+ return Iosb;
+}
+
NTSTATUS
NTAPI
FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
ULONG CreateDisposition;
/* Control blocks */
- PVCB Vcb, DecodedVcb;
- PFCB Fcb, NextFcb;
- PCCB Ccb;
+ PVCB Vcb, DecodedVcb, RelatedVcb;
+ PFCB Fcb, NextFcb, RelatedDcb;
+ PCCB Ccb, RelatedCcb;
PFCB ParentDcb;
/* IRP data */
BOOLEAN EndBackslash = FALSE, OpenedAsDos;
UNICODE_STRING RemainingPart, FirstName, NextName;
OEM_STRING AnsiFirstName;
+ FF_ERROR FfError;
+ TYPE_OF_OPEN TypeOfOpen;
Iosb.Status = STATUS_SUCCESS;
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("FatCommonCreate\n", 0 );
- DPRINT1("Irp = %08lx\n", Irp );
- DPRINT1("\t->Flags = %08lx\n", Irp->Flags );
- DPRINT1("\t->FileObject = %08lx\n", IrpSp->FileObject );
- DPRINT1("\t->RelatedFileObject = %08lx\n", IrpSp->FileObject->RelatedFileObject );
- DPRINT1("\t->FileName = %wZ\n", &IrpSp->FileObject->FileName );
- DPRINT1("\t->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
- DPRINT1("\t->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
- DPRINT1("\t->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
- DPRINT1("\t->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
- DPRINT1("\t->Options = %08lx\n", IrpSp->Parameters.Create.Options );
- DPRINT1("\t->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
- DPRINT1("\t->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
- DPRINT1("\t->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
+ DPRINT("FatCommonCreate\n", 0 );
+ DPRINT("Irp = %08lx\n", Irp );
+ DPRINT("\t->Flags = %08lx\n", Irp->Flags );
+ DPRINT("\t->FileObject = %08lx\n", IrpSp->FileObject );
+ DPRINT("\t->RelatedFileObject = %08lx\n", IrpSp->FileObject->RelatedFileObject );
+ DPRINT("\t->FileName = %wZ\n", &IrpSp->FileObject->FileName );
+ DPRINT("\t->AllocationSize.LowPart = %08lx\n", Irp->Overlay.AllocationSize.LowPart );
+ DPRINT("\t->AllocationSize.HighPart = %08lx\n", Irp->Overlay.AllocationSize.HighPart );
+ DPRINT("\t->SystemBuffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer );
+ DPRINT("\t->DesiredAccess = %08lx\n", IrpSp->Parameters.Create.SecurityContext->DesiredAccess );
+ DPRINT("\t->Options = %08lx\n", IrpSp->Parameters.Create.Options );
+ DPRINT("\t->FileAttributes = %04x\n", IrpSp->Parameters.Create.FileAttributes );
+ DPRINT("\t->ShareAccess = %04x\n", IrpSp->Parameters.Create.ShareAccess );
+ DPRINT("\t->EaLength = %08lx\n", IrpSp->Parameters.Create.EaLength );
/* Apply a special hack for Win32, idea taken from FASTFAT reference driver from WDK */
if ((IrpSp->FileObject->FileName.Length > sizeof(WCHAR)) &&
if (!RelatedFO ||
FatDecodeFileObject(RelatedFO, &DecodedVcb, &Fcb, &Ccb) == UserVolumeOpen)
{
+ /* Check parameters */
+ if (DirectoryFile || OpenTargetDirectory)
+ {
+ Status = DirectoryFile ? STATUS_NOT_A_DIRECTORY : STATUS_INVALID_PARAMETER;
+
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
+
+ /* Complete the request and return */
+ FatCompleteRequest(IrpContext, Irp, Status);
+ return Status;
+ }
+
/* It is indeed a volume open request */
- DPRINT1("Volume open request, not implemented now!\n");
- UNIMPLEMENTED;
+ Iosb = FatiOpenVolume(IrpContext,
+ FileObject,
+ Vcb,
+ DesiredAccess,
+ ShareAccess,
+ CreateDisposition);
+
+ /* Set resulting information */
+ Irp->IoStatus.Information = Iosb.Information;
+
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
+
+ /* Complete the request and return */
+ FatCompleteRequest(IrpContext, Irp, Iosb.Status);
+ return Iosb.Status;
}
}
/* Check if this is a relative open */
if (RelatedFO)
{
- // RelatedFO will be a parent directory
- UNIMPLEMENTED;
+ /* Decode the file object */
+ TypeOfOpen = FatDecodeFileObject(RelatedFO,
+ &RelatedVcb,
+ &RelatedDcb,
+ &RelatedCcb);
+
+ /* Check open type */
+ if (TypeOfOpen != UserFileOpen &&
+ TypeOfOpen != UserDirectoryOpen)
+ {
+ DPRINT1("Invalid file object!\n");
+
+ /* Cleanup and return */
+ FatReleaseVcb(IrpContext, Vcb);
+ return STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+
+ /* File path must be relative */
+ if (FileName.Length != 0 &&
+ FileName.Buffer[0] == L'\\')
+ {
+ /* The name is absolute, fail */
+ FatReleaseVcb(IrpContext, Vcb);
+ return STATUS_OBJECT_NAME_INVALID;
+ }
+
+ /* Make sure volume is the same */
+ ASSERT(RelatedVcb == Vcb);
+
+ /* Save VPB */
+ FileObject->Vpb = RelatedFO->Vpb;
+
+ /* Set parent DCB */
+ ParentDcb = RelatedDcb;
+
+ DPRINT1("Opening file '%wZ' relatively to '%wZ'\n", &FileName, &ParentDcb->FullFileName);
}
else
{
{
/* Not a root dir */
ParentDcb = Vcb->RootDcb;
- DPRINT1("ParentDcb %p\n", ParentDcb);
+ DPRINT("ParentDcb %p\n", ParentDcb);
}
/* Check for backslash at the end */
/* Ensure the name is set */
if (!ParentDcb->FullFileName.Buffer)
{
- DPRINT1("ParentDcb->FullFileName.Buffer is NULL\n");
+ /* Set it if it's missing */
+ FatSetFullFileNameInFcb(IrpContext, ParentDcb);
}
/* Check max path length */
ASSERT(FALSE);
}
- DPRINT1("FirstName %wZ, RemainingPart %wZ\n", &FirstName, &RemainingPart);
+ DPRINT("FirstName %wZ, RemainingPart %wZ\n", &FirstName, &RemainingPart);
/* Break if came to the end */
if (!RemainingPart.Length) break;
- // TODO: Create a DCB for this entry
+ /* Create a DCB for this entry */
+ ParentDcb = FatCreateDcb(IrpContext,
+ Vcb,
+ ParentDcb,
+ NULL);
+
+ /* Set its name */
+ FatSetFullNameInFcb(ParentDcb, &FirstName);
}
- // TODO: Try to open directory
+ /* Try to open it and get a result, saying if this is a dir or a file */
+ FfError = FatiTryToOpen(FileObject, Vcb);
+
+ /* Check if we need to open target directory */
+ if (OpenTargetDirectory)
+ {
+ // TODO: Open target directory
+ UNIMPLEMENTED;
+ }
+
+ /* Check, if path is a directory or a file */
+ if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR)
+ {
+ 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 */
+ 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);
+
/* Complete the request */
Iosb.Status = STATUS_OBJECT_NAME_INVALID;
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
Irp->IoStatus.Information = Iosb.Information;
}
+ /* Unlock VCB */
+ FatReleaseVcb(IrpContext, Vcb);
+
/* Complete the request */
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
{
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
- //PVOLUME_DEVICE_OBJECT VolumeDO = (PVOLUME_DEVICE_OBJECT)DeviceObject;
-
- DPRINT1("FatCreate()\n");
/* If it's called with our Disk FS device object - it's always open */
// TODO: Add check for CDROM FS device object