Don't check the share access for directories.
[reactos.git] / reactos / drivers / fs / vfat / create.c
index 604ec0d..dbcef14 100644 (file)
@@ -16,8 +16,7 @@
  *  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 *****************************************************************/
@@ -43,20 +36,20 @@ void  vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
   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)
@@ -75,9 +68,9 @@ void  vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
        }
       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;
@@ -115,7 +108,7 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
   NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
   *(Vpb->VolumeLabel) = 0;
   Vpb->VolumeLabelLength = 0;
-  
+
   if (DeviceExt->Flags & VCB_IS_FATX)
   {
     SizeDirEntry = sizeof(FATX_DIR_ENTRY);
@@ -156,7 +149,7 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
        {
           break;
        }
-       DirIndex++;       
+       DirIndex++;
        Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
        if ((DirIndex % EntriesPerPage) == 0)
        {
@@ -192,7 +185,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
  */
 {
   PWCHAR PathNameBuffer;
-  ULONG PathNameBufferLength;
+  USHORT PathNameBufferLength;
   NTSTATUS Status;
   PVOID Context = NULL;
   PVOID Page;
@@ -202,19 +195,12 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
   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;
@@ -244,7 +230,12 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
       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);
@@ -252,7 +243,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
              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
@@ -275,7 +266,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
     ExFreePool(PathNameBuffer);
     return Status;
   }
-  
+
   while(TRUE)
     {
       Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
@@ -379,7 +370,7 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PVFATFCB* Pa
                                         0,
                                         FALSE);
 
-      if (Status == STATUS_VERIFY_REQUIRED) 
+      if (Status == STATUS_VERIFY_REQUIRED)
 
         {
           PDEVICE_OBJECT DeviceToVerify;
@@ -388,7 +379,7 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PVFATFCB* Pa
           DPRINT ("Device %p\n", DeviceExt->StorageDevice);
 
          DeviceToVerify = IoGetDeviceToVerify (PsGetCurrentThread ());
-         
+
          IoSetDeviceToVerify (PsGetCurrentThread (),
                               NULL);
           Status = IoVerifyVolume (DeviceExt->StorageDevice,
@@ -441,55 +432,6 @@ VfatOpenFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PVFATFCB* Pa
   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)
 /*
@@ -509,7 +451,7 @@ 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);
@@ -527,9 +469,9 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
     }
 
   /* 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)
@@ -578,7 +520,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
          Dots = FALSE;
        }
 
-      if (*c != '\\' && vfatIsLongIllegal(*c)) 
+      if (*c != '\\' && vfatIsLongIllegal(*c))
         {
           return(STATUS_OBJECT_NAME_INVALID);
        }
@@ -614,22 +556,27 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
        {
          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);
 
@@ -665,14 +612,15 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
       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);
@@ -682,13 +630,13 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
       /*
        * 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);
@@ -698,11 +646,11 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
       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)
@@ -726,7 +674,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
              return(STATUS_INVALID_PARAMETER);
            }
        }
-        
+
 
       if (RequestedDisposition == FILE_OVERWRITE ||
           RequestedDisposition == FILE_OVERWRITE_IF)
@@ -742,12 +690,13 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
              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)
@@ -760,7 +709,8 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
        }
     }
 
-  if (pFcb->OpenHandleCount == 0)
+  if (pFcb->OpenHandleCount == 0 &&
+      !(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
   {
       IoSetShareAccess(Stack->Parameters.Create.SecurityContext->DesiredAccess,
                    Stack->Parameters.Create.ShareAccess,
@@ -773,11 +723,11 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
           FileObject,
           &pFcb->FCBShareAccess
          );
-      
+
    }
 
   pFcb->OpenHandleCount++;
-  
+
   /* FIXME : test write access if requested */
 
   return(Status);
@@ -815,7 +765,7 @@ NTSTATUS VfatCreate (PVFAT_IRP_CONTEXT IrpContext)
   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);