ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

Definition at line 744 of file rw.c.

Referenced by VfatDispatchRequest().

{
   PVFATFCB Fcb;
   PERESOURCE Resource = NULL;
   LARGE_INTEGER ByteOffset;
   LARGE_INTEGER OldFileSize;
   NTSTATUS Status = STATUS_SUCCESS;
   ULONG Length = 0;
   PVOID Buffer;
   ULONG BytesPerSector;

   ASSERT(IrpContext);

   DPRINT("VfatWrite(IrpContext %p)\n", IrpContext);

   ASSERT(IrpContext->DeviceObject);

   // This request is not allowed on the main device object
   if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
   {
      DPRINT("VfatWrite is called with the main device object.\n");
      Status = STATUS_INVALID_DEVICE_REQUEST;
      goto ByeBye;
   }

   ASSERT(IrpContext->DeviceExt);
   ASSERT(IrpContext->FileObject);
   Fcb = IrpContext->FileObject->FsContext;
   ASSERT(Fcb);

   if (Fcb->Flags & FCB_IS_PAGE_FILE)
   {
       PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
       IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
       IoSkipCurrentIrpStackLocation(IrpContext->Irp);
       DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
       Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
       VfatFreeIrpContext(IrpContext);
       return Status;
   }

   DPRINT("<%wZ>\n", &Fcb->PathNameU);

  /* fail if file is a directory and no paged read */
   if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
   {
      Status = STATUS_INVALID_PARAMETER;
      goto ByeBye;
   }

   ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
   if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
       ByteOffset.u.HighPart == -1)
   {
      ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
   }
   Length = IrpContext->Stack->Parameters.Write.Length;
   BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;

   if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
   {
      Status = STATUS_INVALID_PARAMETER;
      goto ByeBye;
   }

   if (Fcb->Flags & (FCB_IS_FAT | FCB_IS_VOLUME) ||
       1 == vfatDirEntryGetFirstCluster (IrpContext->DeviceExt, &Fcb->entry))
   {
      if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
      {
         // we can't extend the FAT, the volume or the root on FAT12/FAT16
         Status = STATUS_END_OF_FILE;
         goto ByeBye;
      }
   }

   if (IrpContext->Irp->Flags & (IRP_PAGING_IO|IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME))
   {
      if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
      {
         // non cached write must be sector aligned
         Status = STATUS_INVALID_PARAMETER;
         goto ByeBye;
      }
   }

   if (Length == 0)
   {
      /* FIXME:
       *   Update last write time
       */
      IrpContext->Irp->IoStatus.Information = 0;
      Status = STATUS_SUCCESS;
      goto ByeBye;
   }

   if (IrpContext->Irp->Flags & IRP_PAGING_IO)
   {
      if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
      {
         Status = STATUS_INVALID_PARAMETER;
         goto ByeBye;
      }
      if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
      {
         Length =  ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
      }
   }

   if (Fcb->Flags & FCB_IS_VOLUME)
   {
      Resource = &IrpContext->DeviceExt->DirResource;
   }
   else if (IrpContext->Irp->Flags & IRP_PAGING_IO)
   {
      Resource = &Fcb->PagingIoResource;
   }
   else
   {
      Resource = &Fcb->MainResource;
   }

   if (Fcb->Flags & FCB_IS_PAGE_FILE)
   {
      if (!ExAcquireResourceSharedLite(Resource,
                                       (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
      {
         Resource = NULL;
         Status = STATUS_PENDING;
         goto ByeBye;
      }
   }
   else
   {
      if (!ExAcquireResourceExclusiveLite(Resource,
                                          (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
      {
         Resource = NULL;
         Status = STATUS_PENDING;
         goto ByeBye;
      }
   }

   if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
      FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
   {
      if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
      {
         Status = STATUS_FILE_LOCK_CONFLICT;
         goto ByeBye;
       }
    }

   if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT) && !(Fcb->Flags & FCB_IS_VOLUME))
   {
      if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
      {
        Status = STATUS_PENDING;
        goto ByeBye;
      }
   }

   OldFileSize = Fcb->RFCB.FileSize;

   Buffer = VfatGetUserBuffer(IrpContext->Irp);
   if (!Buffer)
     {
       Status = STATUS_INVALID_USER_BUFFER;
       goto ByeBye;
     }


   if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) &&
       !(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
       ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
   {
      LARGE_INTEGER AllocationSize;
      AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
      Status = VfatSetAllocationSizeInformation(IrpContext->FileObject, Fcb,
                                            IrpContext->DeviceExt, &AllocationSize);
      if (!NT_SUCCESS (Status))
      {
         goto ByeBye;
      }
   }

   if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
      !(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
   {
      // cached write

      if (IrpContext->FileObject->PrivateCacheMap == NULL)
      {
         CcInitializeCacheMap(IrpContext->FileObject,
                              (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
                              FALSE,
                              &VfatGlobalData->CacheMgrCallbacks,
                              Fcb);
      }
      if (ByteOffset.QuadPart > OldFileSize.QuadPart)
      {
         CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
      }
      if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length,
                      1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer))
      {
         IrpContext->Irp->IoStatus.Information = Length;
         Status = STATUS_SUCCESS;
      }
      else
      {
         Status = STATUS_UNSUCCESSFUL;
      }
   }
   else
   {
      // non cached write

      if (ByteOffset.QuadPart > OldFileSize.QuadPart)
      {
         CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
      }

      Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
      if (!NT_SUCCESS(Status))
        {
      goto ByeBye;
    }

      Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
      if (NT_SUCCESS(Status))
      {
         IrpContext->Irp->IoStatus.Information = Length;
      }
   }

   if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
      !(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
   {
      if(!(*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
      {
         LARGE_INTEGER SystemTime;
         // set dates and times
         KeQuerySystemTime (&SystemTime);
         if (Fcb->Flags & FCB_IS_FATX_ENTRY)
         {
            FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
                                     &SystemTime, &Fcb->entry.FatX.UpdateDate,
                                     &Fcb->entry.FatX.UpdateTime);
            Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
            Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
         }
         else
         {
            FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
                                     &SystemTime, &Fcb->entry.Fat.UpdateDate,
                                     &Fcb->entry.Fat.UpdateTime);
            Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
         }
         /* set date and times to dirty */
     Fcb->Flags |= FCB_IS_DIRTY;
      }
   }

ByeBye:
   if (Resource)
   {
      ExReleaseResourceLite(Resource);
   }

   if (Status == STATUS_PENDING)
   {
      Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
      if (NT_SUCCESS(Status))
      {
         Status = VfatQueueRequest(IrpContext);
      }
      else
      {
         IrpContext->Irp->IoStatus.Status = Status;
         IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
         VfatFreeIrpContext(IrpContext);
      }
   }
   else
   {
      IrpContext->Irp->IoStatus.Status = Status;
      if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO &&
          !(IrpContext->Irp->Flags & IRP_PAGING_IO) && NT_SUCCESS(Status))
      {
         IrpContext->FileObject->CurrentByteOffset.QuadPart =
           ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
      }

      IoCompleteRequest(IrpContext->Irp,
                        (CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
      VfatFreeIrpContext(IrpContext);
   }
   DPRINT("%x\n", Status);
   return Status;
}

Generated on Sun May 27 2012 05:11:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.