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

volume.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS kernel
00004  * FILE:             drivers/fs/vfat/volume.c
00005  * PURPOSE:          VFAT Filesystem
00006  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
00007  *                   Herve Poussineau (reactos@poussine.freesurf.fr)
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #define NDEBUG
00013 #include "vfat.h"
00014 
00015 /* FUNCTIONS ****************************************************************/
00016 
00017 static NTSTATUS
00018 FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
00019               PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
00020               PULONG BufferLength)
00021 {
00022   DPRINT("FsdGetFsVolumeInformation()\n");
00023   DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
00024   DPRINT("BufferLength %lu\n", *BufferLength);
00025 
00026   DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength));
00027   DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength);
00028   DPRINT("Label %*.S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel);
00029 
00030   if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
00031     return STATUS_INFO_LENGTH_MISMATCH;
00032 
00033   if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
00034     return STATUS_BUFFER_OVERFLOW;
00035 
00036   /* valid entries */
00037   FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
00038   FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
00039   RtlCopyMemory(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel, FsVolumeInfo->VolumeLabelLength);
00040 
00041   /* dummy entries */
00042   FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
00043   FsVolumeInfo->SupportsObjects = FALSE;
00044 
00045   DPRINT("Finished FsdGetFsVolumeInformation()\n");
00046 
00047   *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
00048 
00049   DPRINT("BufferLength %lu\n", *BufferLength);
00050 
00051   return(STATUS_SUCCESS);
00052 }
00053 
00054 
00055 static NTSTATUS
00056 FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
00057                  PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
00058                  PULONG BufferLength)
00059 {
00060   PCWSTR pName; ULONG Length;
00061   DPRINT("FsdGetFsAttributeInformation()\n");
00062   DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
00063   DPRINT("BufferLength %lu\n", *BufferLength);
00064 
00065   if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
00066     return STATUS_INFO_LENGTH_MISMATCH;
00067 
00068   if (DeviceExt->FatInfo.FatType == FAT32)
00069   {
00070     Length = 10;
00071     pName = L"FAT32";
00072   }
00073   else
00074   {
00075     Length = 6;
00076     pName = L"FAT";
00077   }
00078 
00079   DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length));
00080 
00081   if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length))
00082     return STATUS_BUFFER_OVERFLOW;
00083 
00084   FsAttributeInfo->FileSystemAttributes =
00085     FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
00086 
00087   FsAttributeInfo->MaximumComponentNameLength = 255;
00088 
00089   FsAttributeInfo->FileSystemNameLength = Length;
00090 
00091   RtlCopyMemory(FsAttributeInfo->FileSystemName, pName, Length );
00092 
00093   DPRINT("Finished FsdGetFsAttributeInformation()\n");
00094 
00095   *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length);
00096   DPRINT("BufferLength %lu\n", *BufferLength);
00097 
00098   return(STATUS_SUCCESS);
00099 }
00100 
00101 
00102 static NTSTATUS
00103 FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
00104             PFILE_FS_SIZE_INFORMATION FsSizeInfo,
00105             PULONG BufferLength)
00106 {
00107   PDEVICE_EXTENSION DeviceExt;
00108   NTSTATUS Status;
00109 
00110   DPRINT("FsdGetFsSizeInformation()\n");
00111   DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
00112 
00113   if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
00114     return(STATUS_BUFFER_OVERFLOW);
00115 
00116   DeviceExt = DeviceObject->DeviceExtension;
00117   Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits);
00118 
00119   FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters;
00120   FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster;
00121   FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
00122 
00123   DPRINT("Finished FsdGetFsSizeInformation()\n");
00124   if (NT_SUCCESS(Status))
00125     *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
00126 
00127   return(Status);
00128 }
00129 
00130 
00131 static NTSTATUS
00132 FsdGetFsDeviceInformation
00133 (
00134   PDEVICE_OBJECT DeviceObject,
00135   PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
00136   PULONG BufferLength
00137 )
00138 {
00139   DPRINT("FsdGetFsDeviceInformation()\n");
00140   DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
00141   DPRINT("BufferLength %lu\n", *BufferLength);
00142   DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
00143 
00144   if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
00145     return(STATUS_BUFFER_OVERFLOW);
00146 
00147   FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
00148   FsDeviceInfo->Characteristics = DeviceObject->Characteristics;
00149 
00150   DPRINT("FsdGetFsDeviceInformation() finished.\n");
00151 
00152   *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
00153   DPRINT("BufferLength %lu\n", *BufferLength);
00154 
00155   return(STATUS_SUCCESS);
00156 }
00157 
00158 
00159 static NTSTATUS
00160 FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
00161              PFILE_FS_LABEL_INFORMATION FsLabelInfo)
00162 {
00163   PDEVICE_EXTENSION DeviceExt;
00164   PVOID Context = NULL;
00165   ULONG DirIndex = 0;
00166   PDIR_ENTRY Entry;
00167   PVFATFCB pRootFcb;
00168   LARGE_INTEGER FileOffset;
00169   BOOLEAN LabelFound = FALSE;
00170   DIR_ENTRY VolumeLabelDirEntry;
00171   ULONG VolumeLabelDirIndex;
00172   ULONG LabelLen;
00173   NTSTATUS Status = STATUS_UNSUCCESSFUL;
00174   OEM_STRING StringO;
00175   UNICODE_STRING StringW;
00176   CHAR cString[43];
00177   ULONG SizeDirEntry;
00178   ULONG EntriesPerPage;
00179 
00180   DPRINT("FsdSetFsLabelInformation()\n");
00181 
00182   DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00183 
00184   if (sizeof(DeviceObject->Vpb->VolumeLabel) < FsLabelInfo->VolumeLabelLength)
00185   {
00186     return STATUS_NAME_TOO_LONG;
00187   }
00188 
00189   if (DeviceExt->Flags & VCB_IS_FATX)
00190   {
00191     if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 42)
00192       return STATUS_NAME_TOO_LONG;
00193     SizeDirEntry = sizeof(FATX_DIR_ENTRY);
00194     EntriesPerPage = FATX_ENTRIES_PER_PAGE;
00195   }
00196   else
00197   {
00198     if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 11)
00199       return STATUS_NAME_TOO_LONG;
00200     SizeDirEntry = sizeof(FAT_DIR_ENTRY);
00201     EntriesPerPage = FAT_ENTRIES_PER_PAGE;
00202   }
00203 
00204   /* Create Volume label dir entry */
00205   LabelLen = FsLabelInfo->VolumeLabelLength / sizeof(WCHAR);
00206   RtlZeroMemory(&VolumeLabelDirEntry, SizeDirEntry);
00207   StringW.Buffer = FsLabelInfo->VolumeLabel;
00208   StringW.Length = StringW.MaximumLength = (USHORT)FsLabelInfo->VolumeLabelLength;
00209   StringO.Buffer = cString;
00210   StringO.Length = 0;
00211   StringO.MaximumLength = 42;
00212   Status = RtlUnicodeStringToOemString(&StringO, &StringW, FALSE);
00213   if (!NT_SUCCESS(Status))
00214     return Status;
00215   if (DeviceExt->Flags & VCB_IS_FATX)
00216   {
00217     RtlCopyMemory(VolumeLabelDirEntry.FatX.Filename, cString, LabelLen);
00218     memset(&VolumeLabelDirEntry.FatX.Filename[LabelLen], ' ', 42 - LabelLen);
00219     VolumeLabelDirEntry.FatX.Attrib = _A_VOLID;
00220   }
00221   else
00222   {
00223     RtlCopyMemory(VolumeLabelDirEntry.Fat.Filename, cString, max(sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen));
00224     if (LabelLen > sizeof(VolumeLabelDirEntry.Fat.Filename))
00225     {
00226       memset(VolumeLabelDirEntry.Fat.Ext, ' ', sizeof(VolumeLabelDirEntry.Fat.Ext));
00227       RtlCopyMemory(VolumeLabelDirEntry.Fat.Ext, cString + sizeof(VolumeLabelDirEntry.Fat.Filename), LabelLen - sizeof(VolumeLabelDirEntry.Fat.Filename));
00228     }
00229     else
00230     {
00231       memset(&VolumeLabelDirEntry.Fat.Filename[LabelLen], ' ', sizeof(VolumeLabelDirEntry.Fat.Filename) - LabelLen);
00232     }
00233     VolumeLabelDirEntry.Fat.Attrib = _A_VOLID;
00234   }
00235 
00236   pRootFcb = vfatOpenRootFCB(DeviceExt);
00237 
00238   /* Search existing volume entry on disk */
00239   FileOffset.QuadPart = 0;
00240   if (CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
00241   {
00242     while (TRUE)
00243     {
00244       if (ENTRY_VOLUME(DeviceExt, Entry))
00245       {
00246         /* Update entry */
00247         LabelFound = TRUE;
00248         RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
00249         CcSetDirtyPinnedData(Context, NULL);
00250         Status = STATUS_SUCCESS;
00251         break;
00252       }
00253       if (ENTRY_END(DeviceExt, Entry))
00254       {
00255         break;
00256       }
00257       DirIndex++;
00258       Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
00259       if ((DirIndex % EntriesPerPage) == 0)
00260       {
00261         CcUnpinData(Context);
00262         FileOffset.u.LowPart += PAGE_SIZE;
00263         if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry, TRUE, &Context, (PVOID*)&Entry))
00264         {
00265           Context = NULL;
00266           break;
00267         }
00268       }
00269     }
00270     if (Context)
00271     {
00272       CcUnpinData(Context);
00273     }
00274   }
00275   if (!LabelFound)
00276   {
00277     /* Add new entry for label */
00278     if (!vfatFindDirSpace(DeviceExt, pRootFcb, 1, &VolumeLabelDirIndex))
00279       Status = STATUS_DISK_FULL;
00280     else
00281     {
00282       FileOffset.u.HighPart = 0;
00283       FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry;
00284       if (!CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry,
00285                  TRUE, &Context, (PVOID*)&Entry))
00286       {
00287           Status = STATUS_UNSUCCESSFUL;
00288       }
00289       else
00290       {
00291           RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
00292           CcSetDirtyPinnedData(Context, NULL);
00293           CcUnpinData(Context);
00294           Status = STATUS_SUCCESS;
00295       }
00296     }
00297   }
00298 
00299   vfatReleaseFCB(DeviceExt, pRootFcb);
00300   if (!NT_SUCCESS(Status))
00301   {
00302     return Status;
00303   }
00304 
00305   /* Update volume label in memory */
00306   DeviceObject->Vpb->VolumeLabelLength = (USHORT)FsLabelInfo->VolumeLabelLength;
00307   RtlCopyMemory(DeviceObject->Vpb->VolumeLabel, FsLabelInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabelLength);
00308 
00309   return Status;
00310 }
00311 
00312 
00313 NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
00314 /*
00315  * FUNCTION: Retrieve the specified volume information
00316  */
00317 {
00318   FS_INFORMATION_CLASS FsInformationClass;
00319   NTSTATUS RC = STATUS_SUCCESS;
00320   PVOID SystemBuffer;
00321   ULONG BufferLength;
00322 
00323   /* PRECONDITION */
00324   ASSERT(IrpContext);
00325 
00326   DPRINT("VfatQueryVolumeInformation(IrpContext %p)\n", IrpContext);
00327 
00328   if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
00329                                    (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
00330   {
00331      return VfatQueueRequest (IrpContext);
00332   }
00333 
00334   /* INITIALIZATION */
00335   FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
00336   BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
00337   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
00338 
00339 
00340   DPRINT ("FsInformationClass %d\n", FsInformationClass);
00341   DPRINT ("SystemBuffer %p\n", SystemBuffer);
00342 
00343   switch (FsInformationClass)
00344     {
00345     case FileFsVolumeInformation:
00346       RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
00347                      SystemBuffer,
00348                      &BufferLength);
00349       break;
00350 
00351     case FileFsAttributeInformation:
00352       RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension,
00353                     SystemBuffer,
00354                     &BufferLength);
00355       break;
00356 
00357     case FileFsSizeInformation:
00358       RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
00359                    SystemBuffer,
00360                    &BufferLength);
00361       break;
00362 
00363     case FileFsDeviceInformation:
00364       RC = FsdGetFsDeviceInformation(IrpContext->DeviceObject,
00365                      SystemBuffer,
00366                      &BufferLength);
00367       break;
00368 
00369     default:
00370       RC = STATUS_NOT_SUPPORTED;
00371     }
00372 
00373   ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
00374   IrpContext->Irp->IoStatus.Status = RC;
00375   if (NT_SUCCESS(RC))
00376     IrpContext->Irp->IoStatus.Information =
00377       IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;
00378   else
00379     IrpContext->Irp->IoStatus.Information = 0;
00380   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
00381   VfatFreeIrpContext(IrpContext);
00382 
00383   return RC;
00384 }
00385 
00386 
00387 NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
00388 /*
00389  * FUNCTION: Set the specified volume information
00390  */
00391 {
00392   FS_INFORMATION_CLASS FsInformationClass;
00393   NTSTATUS Status = STATUS_SUCCESS;
00394   PVOID SystemBuffer;
00395   ULONG BufferLength;
00396   PIO_STACK_LOCATION Stack = IrpContext->Stack;
00397 
00398   /* PRECONDITION */
00399   ASSERT(IrpContext);
00400 
00401   DPRINT ("VfatSetVolumeInformation(IrpContext %p)\n", IrpContext);
00402 
00403   if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
00404                                       (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
00405   {
00406      return VfatQueueRequest (IrpContext);
00407   }
00408 
00409   FsInformationClass = Stack->Parameters.SetVolume.FsInformationClass;
00410   BufferLength = Stack->Parameters.SetVolume.Length;
00411   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
00412 
00413   DPRINT ("FsInformationClass %d\n", FsInformationClass);
00414   DPRINT ("BufferLength %d\n", BufferLength);
00415   DPRINT ("SystemBuffer %p\n", SystemBuffer);
00416 
00417   switch(FsInformationClass)
00418     {
00419     case FileFsLabelInformation:
00420       Status = FsdSetFsLabelInformation(IrpContext->DeviceObject,
00421                     SystemBuffer);
00422       break;
00423 
00424     default:
00425       Status = STATUS_NOT_SUPPORTED;
00426     }
00427 
00428   ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
00429   IrpContext->Irp->IoStatus.Status = Status;
00430   IrpContext->Irp->IoStatus.Information = 0;
00431   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
00432   VfatFreeIrpContext(IrpContext);
00433 
00434   return(Status);
00435 }
00436 
00437 /* EOF */

Generated on Mon May 28 2012 04:19:04 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.