* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id$
- *
+/*
* PROJECT: ReactOS kernel
* FILE: drivers/fs/vfat/create.c
* PURPOSE: VFAT Filesystem
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <wchar.h>
-#include <limits.h>
-
#define NDEBUG
-#include <debug.h>
-
#include "vfat.h"
/* FUNCTIONS *****************************************************************/
OEM_STRING StringA;
USHORT Length;
CHAR cString[12];
-
- RtlCopyMemory(cString, pEntry->Filename, 11);
+
+ RtlCopyMemory(cString, pEntry->ShortName, 11);
cString[11] = 0;
if (cString[0] == 0x05)
{
cString[0] = 0xe5;
- }
+ }
StringA.Buffer = cString;
- for (StringA.Length = 0;
+ for (StringA.Length = 0;
StringA.Length < 8 && StringA.Buffer[StringA.Length] != ' ';
StringA.Length++);
StringA.MaximumLength = StringA.Length;
-
+
RtlOemStringToUnicodeString(NameU, &StringA, FALSE);
if (pEntry->lCase & VFAT_CASE_LOWER_BASE)
}
NameU->Length = 0;
NameU->MaximumLength -= Length;
-
+
StringA.Buffer = &cString[8];
- for (StringA.Length = 0;
+ for (StringA.Length = 0;
StringA.Length < 3 && StringA.Buffer[StringA.Length] != ' ';
StringA.Length++);
StringA.MaximumLength = StringA.Length;
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
*(Vpb->VolumeLabel) = 0;
Vpb->VolumeLabelLength = 0;
-
+
if (DeviceExt->Flags & VCB_IS_FATX)
{
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
{
break;
}
- DirIndex++;
+ DirIndex++;
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
if ((DirIndex % EntriesPerPage) == 0)
{
*/
{
PWCHAR PathNameBuffer;
- ULONG PathNameBufferLength;
+ USHORT PathNameBufferLength;
NTSTATUS Status;
PVOID Context = NULL;
PVOID Page;
UNICODE_STRING FileToFindUpcase;
BOOLEAN WildCard;
- DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
+ DPRINT ("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
Parent, FileToFindU, DirContext->DirIndex);
DPRINT ("FindFile: Path %wZ)\n",&Parent->PathNameU);
-
- PathNameBufferLength = Parent->PathNameU.Length + LONGNAME_MAX_LENGTH + 2 * sizeof(WCHAR);
- if (PathNameBufferLength > (USHRT_MAX - 2) * sizeof(WCHAR))
- {
- /* A valid filename can't be so long. Do as if the file doesn't exist. */
- CHECKPOINT;
- return STATUS_NO_SUCH_FILE;
- }
-
- PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength);
+
+ PathNameBufferLength = LONGNAME_MAX_LENGTH * sizeof(WCHAR);
+ PathNameBuffer = ExAllocatePool(NonPagedPool, PathNameBufferLength + sizeof(WCHAR));
if (!PathNameBuffer)
{
CHECKPOINT1;
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb)
{
- if(rcFcb->startIndex >= DirContext->DirIndex)
+ ULONG startIndex = rcFcb->startIndex;
+ if ((rcFcb->Flags & FCB_IS_FATX_ENTRY) && !vfatFCBIsRoot(Parent))
+ {
+ startIndex += 2;
+ }
+ if(startIndex >= DirContext->DirIndex)
{
RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
DirContext->StartIndex = rcFcb->startIndex;
DirContext->DirIndex = rcFcb->dirIndex;
DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
- &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
+ &DirContext->LongNameU, DirContext->DirIndex, DirContext->StartIndex);
Status = STATUS_SUCCESS;
}
else
ExFreePool(PathNameBuffer);
return Status;
}
-
+
while(TRUE)
{
Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
0,
FALSE);
- if (Status == STATUS_VERIFY_REQUIRED)
+ if (Status == STATUS_VERIFY_REQUIRED)
{
PDEVICE_OBJECT DeviceToVerify;
DPRINT ("Device %p\n", DeviceExt->StorageDevice);
DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
-
+
IoSetDeviceToVerify (PsGetCurrentThread (),
NULL);
Status = IoVerifyVolume (DeviceExt->StorageDevice,
return Status;
}
-VOID STATIC
-VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
- PVFATFCB Fcb)
-{
- ULONG Cluster, NextCluster;
- NTSTATUS Status;
-
- if (Fcb->Flags & FCB_IS_FATX_ENTRY)
- {
- Fcb->entry.FatX.FileSize = 0;
- Cluster = Fcb->entry.FatX.FirstCluster;
- Fcb->entry.FatX.FirstCluster = 0;
- }
- else
- {
- Fcb->entry.Fat.FileSize = 0;
- if (DeviceExt->FatInfo.FatType == FAT32)
- {
- Cluster = Fcb->entry.Fat.FirstCluster + Fcb->entry.Fat.FirstClusterHigh * 65536;
- }
- else
- {
- Cluster = Fcb->entry.Fat.FirstCluster;
- }
- Fcb->entry.Fat.FirstCluster = 0;
- Fcb->entry.Fat.FirstClusterHigh = 0;
- }
- Fcb->LastOffset = Fcb->LastCluster = 0;
- VfatUpdateEntry (Fcb);
- if (Fcb->RFCB.FileSize.QuadPart > 0)
- {
- Fcb->RFCB.AllocationSize.QuadPart = 0;
- Fcb->RFCB.FileSize.QuadPart = 0;
- Fcb->RFCB.ValidDataLength.QuadPart = 0;
- /* Notify cache manager about the change in file size if caching is
- initialized on the file stream */
- if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
- {
- CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->RFCB.AllocationSize);
- }
- }
- while (Cluster != 0xffffffff && Cluster > 1)
- {
- Status = GetNextCluster (DeviceExt, Cluster, &NextCluster);
- WriteCluster (DeviceExt, Cluster, 0);
- Cluster = NextCluster;
- }
-}
-
NTSTATUS
VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
LARGE_INTEGER AllocationSize;
BOOLEAN Dots;
UNICODE_STRING FileNameU;
-
+
/* Unpack the various parameters. */
Stack = IoGetCurrentIrpStackLocation (Irp);
RequestedDisposition = ((Stack->Parameters.Create.Options >> 24) & 0xff);
}
/* This a open operation for the volume itself */
- if (FileObject->FileName.Length == 0 &&
+ if (FileObject->FileName.Length == 0 &&
FileObject->RelatedFileObject == NULL)
- {
+ {
if (RequestedDisposition == FILE_CREATE ||
RequestedDisposition == FILE_OVERWRITE_IF ||
RequestedDisposition == FILE_SUPERSEDE)
Dots = FALSE;
}
- if (*c != '\\' && vfatIsLongIllegal(*c))
+ if (*c != '\\' && vfatIsLongIllegal(*c))
{
return(STATUS_OBJECT_NAME_INVALID);
}
{
ULONG Attributes;
Attributes = Stack->Parameters.Create.FileAttributes;
-
+
vfatSplitPathName(&FileObject->FileName, NULL, &FileNameU);
- Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
+ Status = VfatAddEntry (DeviceExt, &FileNameU, &pFcb, ParentFcb, RequestedOptions,
(UCHAR)(Attributes & FILE_ATTRIBUTE_VALID_FLAGS));
vfatReleaseFCB (DeviceExt, ParentFcb);
if (NT_SUCCESS (Status))
{
- vfatAttachFCBToFileObject (DeviceExt, pFcb, FileObject);
-
+ Status = vfatAttachFCBToFileObject (DeviceExt, pFcb, FileObject);
+ if ( !NT_SUCCESS(Status) )
+ {
+ vfatReleaseFCB (DeviceExt, pFcb);
+ return Status;
+ }
+
Irp->IoStatus.Information = FILE_CREATED;
-
- VfatSetAllocationSizeInformation(FileObject,
+
+ VfatSetAllocationSizeInformation(FileObject,
pFcb,
DeviceExt,
&Irp->Overlay.AllocationSize);
- VfatSetExtendedAttributes(FileObject,
+ VfatSetExtendedAttributes(FileObject,
Irp->AssociatedIrp.SystemBuffer,
Stack->Parameters.Create.EaLength);
pFcb = FileObject->FsContext;
- if (pFcb->OpenHandleCount != 0)
+ if (pFcb->OpenHandleCount != 0 &&
+ !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
Status = IoCheckShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
Stack->Parameters.Create.ShareAccess,
FileObject,
&pFcb->FCBShareAccess,
FALSE);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
VfatCloseFile (DeviceExt, FileObject);
return(Status);
/*
* Check the file has the requested attributes
*/
- if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
+ 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 &&
+ if (RequestedOptions & FILE_DIRECTORY_FILE &&
!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
VfatCloseFile (DeviceExt, FileObject);
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
+ * 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)
return(STATUS_INVALID_PARAMETER);
}
}
-
+
if (RequestedDisposition == FILE_OVERWRITE ||
RequestedDisposition == FILE_OVERWRITE_IF)
return(Status);
}
}
-
-
+
+
/* Supersede the file */
if (RequestedDisposition == FILE_SUPERSEDE)
{
- VfatSupersedeFile(DeviceExt, FileObject, pFcb);
+ AllocationSize.QuadPart = 0;
+ VfatSetAllocationSizeInformation(FileObject, pFcb, DeviceExt, &AllocationSize);
Irp->IoStatus.Information = FILE_SUPERSEDED;
}
else if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF)
}
}
- if (pFcb->OpenHandleCount == 0)
+ if (pFcb->OpenHandleCount == 0 &&
+ !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
Stack->Parameters.Create.ShareAccess,
FileObject,
&pFcb->FCBShareAccess
);
-
+
}
pFcb->OpenHandleCount++;
-
+
/* FIXME : test write access if requested */
return(Status);
ExReleaseResourceLite (&IrpContext->DeviceExt->DirResource);
IrpContext->Irp->IoStatus.Status = Status;
- IoCompleteRequest (IrpContext->Irp,
+ IoCompleteRequest (IrpContext->Irp,
(CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
VfatFreeIrpContext(IrpContext);
return(Status);