ReactOS Fundraising Campaign 2012
 
€ 3,873 / € 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

fat.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/fat.c
00005  * PURPOSE:          VFAT Filesystem
00006  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
00007  *
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #define NDEBUG
00013 #include "vfat.h"
00014 
00015 /* GLOBALS ******************************************************************/
00016 
00017 #define  CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->FatInfo.BytesPerCluster > PAGE_SIZE ? \
00018            (pDeviceExt)->FatInfo.BytesPerCluster : PAGE_SIZE)
00019 
00020 /* FUNCTIONS ****************************************************************/
00021 
00022 NTSTATUS
00023 FAT32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
00024             ULONG CurrentCluster,
00025             PULONG NextCluster)
00026 /*
00027  * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
00028  *           disk read
00029  */
00030 {
00031   PVOID BaseAddress;
00032   ULONG FATOffset;
00033   ULONG ChunkSize;
00034   PVOID Context;
00035   LARGE_INTEGER Offset;
00036 
00037   ChunkSize = CACHEPAGESIZE(DeviceExt);
00038   FATOffset = CurrentCluster * sizeof(ULONG);
00039   Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
00040   if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00041   {
00042     return STATUS_UNSUCCESSFUL;
00043   }
00044   CurrentCluster = (*(PULONG)((char*)BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
00045   if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
00046     CurrentCluster = 0xffffffff;
00047   CcUnpinData(Context);
00048   *NextCluster = CurrentCluster;
00049   return (STATUS_SUCCESS);
00050 }
00051 
00052 NTSTATUS
00053 FAT16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
00054             ULONG CurrentCluster,
00055             PULONG NextCluster)
00056 /*
00057  * FUNCTION: Retrieve the next FAT16 cluster from the FAT table
00058  */
00059 {
00060   PVOID BaseAddress;
00061   ULONG FATOffset;
00062   ULONG ChunkSize;
00063   PVOID Context;
00064   LARGE_INTEGER Offset;
00065 
00066   ChunkSize = CACHEPAGESIZE(DeviceExt);
00067   FATOffset = CurrentCluster * 2;
00068   Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
00069   if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, MAP_WAIT, &Context, &BaseAddress))
00070   {
00071     return STATUS_UNSUCCESSFUL;
00072   }
00073   CurrentCluster = *((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
00074   if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
00075     CurrentCluster = 0xffffffff;
00076   CcUnpinData(Context);
00077   *NextCluster = CurrentCluster;
00078   return (STATUS_SUCCESS);
00079 }
00080 
00081 NTSTATUS
00082 FAT12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
00083             ULONG CurrentCluster,
00084             PULONG NextCluster)
00085 /*
00086  * FUNCTION: Retrieve the next FAT12 cluster from the FAT table
00087  */
00088 {
00089   PUSHORT CBlock;
00090   ULONG Entry;
00091   PVOID BaseAddress;
00092   PVOID Context;
00093   LARGE_INTEGER Offset;
00094 
00095 
00096   *NextCluster = 0;
00097 
00098   Offset.QuadPart = 0;
00099   if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
00100   {
00101     return STATUS_UNSUCCESSFUL;
00102   }
00103   CBlock = (PUSHORT)((char*)BaseAddress + (CurrentCluster * 12) / 8);
00104   if ((CurrentCluster % 2) == 0)
00105     {
00106       Entry = *CBlock & 0x0fff;
00107     }
00108   else
00109     {
00110       Entry = *CBlock >> 4;
00111     }
00112 //  DPRINT("Entry %x\n",Entry);
00113   if (Entry >= 0xff8 && Entry <= 0xfff)
00114     Entry = 0xffffffff;
00115 //  DPRINT("Returning %x\n",Entry);
00116   *NextCluster = Entry;
00117   CcUnpinData(Context);
00118 //  return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
00119   return STATUS_SUCCESS;
00120 }
00121 
00122 NTSTATUS
00123 FAT16FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt,
00124                                  PULONG Cluster)
00125 /*
00126  * FUNCTION: Finds the first available cluster in a FAT16 table
00127  */
00128 {
00129   ULONG FatLength;
00130   ULONG StartCluster;
00131   ULONG i, j;
00132   PVOID BaseAddress;
00133   ULONG ChunkSize;
00134   PVOID Context = 0;
00135   LARGE_INTEGER Offset;
00136   PUSHORT Block;
00137   PUSHORT BlockEnd;
00138 
00139   ChunkSize = CACHEPAGESIZE(DeviceExt);
00140   FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
00141   *Cluster = 0;
00142   StartCluster = DeviceExt->LastAvailableCluster;
00143 
00144   for (j = 0; j < 2; j++)
00145   {
00146     for (i = StartCluster; i < FatLength; )
00147     {
00148       Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
00149       if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00150       {
00151         DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
00152         return STATUS_UNSUCCESSFUL;
00153       }
00154       Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
00155       BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
00156 
00157       /* Now process the whole block */
00158       while (Block < BlockEnd && i < FatLength)
00159       {
00160         if (*Block == 0)
00161         {
00162           DPRINT("Found available cluster 0x%x\n", i);
00163           DeviceExt->LastAvailableCluster = *Cluster = i;
00164           *Block = 0xffff;
00165           CcSetDirtyPinnedData(Context, NULL);
00166           CcUnpinData(Context);
00167           if (DeviceExt->AvailableClustersValid)
00168             InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
00169           return(STATUS_SUCCESS);
00170         }
00171 
00172         Block++;
00173         i++;
00174       }
00175 
00176       CcUnpinData(Context);
00177     }
00178     FatLength = StartCluster;
00179     StartCluster = 2;
00180   }
00181   return(STATUS_DISK_FULL);
00182 }
00183 
00184 NTSTATUS
00185 FAT12FindAndMarkAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
00186 /*
00187  * FUNCTION: Finds the first available cluster in a FAT12 table
00188  */
00189 {
00190   ULONG FatLength;
00191   ULONG StartCluster;
00192   ULONG Entry;
00193   PUSHORT CBlock;
00194   ULONG i, j;
00195   PVOID BaseAddress;
00196   PVOID Context;
00197   LARGE_INTEGER Offset;
00198 
00199   FatLength = DeviceExt->FatInfo.NumberOfClusters + 2;
00200   *Cluster = 0;
00201   StartCluster = DeviceExt->LastAvailableCluster;
00202   Offset.QuadPart = 0;
00203   if(!CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
00204   {
00205     DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector);
00206     return STATUS_UNSUCCESSFUL;
00207   }
00208 
00209   for (j = 0; j < 2; j++)
00210   {
00211     for (i = StartCluster; i < FatLength; i++)
00212     {
00213       CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
00214       if ((i % 2) == 0)
00215        {
00216          Entry = *CBlock & 0xfff;
00217        }
00218       else
00219        {
00220          Entry = *CBlock >> 4;
00221        }
00222       if (Entry == 0)
00223        {
00224          DPRINT("Found available cluster 0x%x\n", i);
00225          DeviceExt->LastAvailableCluster = *Cluster = i;
00226          if ((i % 2) == 0)
00227            *CBlock = (*CBlock & 0xf000) | 0xfff;
00228          else
00229            *CBlock = (*CBlock & 0xf) | 0xfff0;
00230          CcSetDirtyPinnedData(Context, NULL);
00231          CcUnpinData(Context);
00232          if (DeviceExt->AvailableClustersValid)
00233            InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
00234          return(STATUS_SUCCESS);
00235        }
00236     }
00237     FatLength = StartCluster;
00238     StartCluster = 2;
00239   }
00240   CcUnpinData(Context);
00241   return (STATUS_DISK_FULL);
00242 }
00243 
00244 NTSTATUS
00245 FAT32FindAndMarkAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
00246 /*
00247  * FUNCTION: Finds the first available cluster in a FAT32 table
00248  */
00249 {
00250   ULONG FatLength;
00251   ULONG StartCluster;
00252   ULONG i, j;
00253   PVOID BaseAddress;
00254   ULONG ChunkSize;
00255   PVOID Context;
00256   LARGE_INTEGER Offset;
00257   PULONG Block;
00258   PULONG BlockEnd;
00259 
00260   ChunkSize = CACHEPAGESIZE(DeviceExt);
00261   FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
00262   *Cluster = 0;
00263   StartCluster = DeviceExt->LastAvailableCluster;
00264 
00265   for (j = 0; j < 2; j++)
00266   {
00267     for (i = StartCluster; i < FatLength;)
00268     {
00269       Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
00270       if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00271       {
00272         DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
00273         return STATUS_UNSUCCESSFUL;
00274       }
00275       Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
00276       BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
00277 
00278       /* Now process the whole block */
00279       while (Block < BlockEnd && i < FatLength)
00280       {
00281         if ((*Block & 0x0fffffff) == 0)
00282         {
00283           DPRINT("Found available cluster 0x%x\n", i);
00284           DeviceExt->LastAvailableCluster = *Cluster = i;
00285           *Block = 0x0fffffff;
00286           CcSetDirtyPinnedData(Context, NULL);
00287           CcUnpinData(Context);
00288           if (DeviceExt->AvailableClustersValid)
00289             InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
00290           return(STATUS_SUCCESS);
00291         }
00292 
00293         Block++;
00294         i++;
00295       }
00296 
00297       CcUnpinData(Context);
00298     }
00299     FatLength = StartCluster;
00300     StartCluster = 2;
00301   }
00302   return (STATUS_DISK_FULL);
00303 }
00304 
00305 static NTSTATUS
00306 FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
00307 /*
00308  * FUNCTION: Counts free cluster in a FAT12 table
00309  */
00310 {
00311   ULONG Entry;
00312   PVOID BaseAddress;
00313   ULONG ulCount = 0;
00314   ULONG i;
00315   ULONG numberofclusters;
00316   LARGE_INTEGER Offset;
00317   PVOID Context;
00318   PUSHORT CBlock;
00319 
00320   Offset.QuadPart = 0;
00321   if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
00322   {
00323     return STATUS_UNSUCCESSFUL;
00324   }
00325 
00326   numberofclusters = DeviceExt->FatInfo.NumberOfClusters + 2;
00327 
00328   for (i = 2; i < numberofclusters; i++)
00329     {
00330     CBlock = (PUSHORT)((char*)BaseAddress + (i * 12) / 8);
00331       if ((i % 2) == 0)
00332     {
00333       Entry = *CBlock & 0x0fff;
00334     }
00335       else
00336     {
00337       Entry = *CBlock >> 4;
00338     }
00339       if (Entry == 0)
00340     ulCount++;
00341     }
00342 
00343   CcUnpinData(Context);
00344   DeviceExt->AvailableClusters = ulCount;
00345   DeviceExt->AvailableClustersValid = TRUE;
00346 
00347   return(STATUS_SUCCESS);
00348 }
00349 
00350 
00351 static NTSTATUS
00352 FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
00353 /*
00354  * FUNCTION: Counts free clusters in a FAT16 table
00355  */
00356 {
00357   PUSHORT Block;
00358   PUSHORT BlockEnd;
00359   PVOID BaseAddress = NULL;
00360   ULONG ulCount = 0;
00361   ULONG i;
00362   ULONG ChunkSize;
00363   PVOID Context = NULL;
00364   LARGE_INTEGER Offset;
00365   ULONG FatLength;
00366 
00367   ChunkSize = CACHEPAGESIZE(DeviceExt);
00368   FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
00369 
00370   for (i = 2; i < FatLength; )
00371   {
00372     Offset.QuadPart = ROUND_DOWN(i * 2, ChunkSize);
00373     if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00374     {
00375       return STATUS_UNSUCCESSFUL;
00376     }
00377     Block = (PUSHORT)((ULONG_PTR)BaseAddress + (i * 2) % ChunkSize);
00378     BlockEnd = (PUSHORT)((ULONG_PTR)BaseAddress + ChunkSize);
00379 
00380     /* Now process the whole block */
00381     while (Block < BlockEnd && i < FatLength)
00382     {
00383       if (*Block == 0)
00384         ulCount++;
00385       Block++;
00386       i++;
00387     }
00388 
00389     CcUnpinData(Context);
00390   }
00391 
00392   DeviceExt->AvailableClusters = ulCount;
00393   DeviceExt->AvailableClustersValid = TRUE;
00394 
00395   return(STATUS_SUCCESS);
00396 }
00397 
00398 
00399 static NTSTATUS
00400 FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
00401 /*
00402  * FUNCTION: Counts free clusters in a FAT32 table
00403  */
00404 {
00405   PULONG Block;
00406   PULONG BlockEnd;
00407   PVOID BaseAddress = NULL;
00408   ULONG ulCount = 0;
00409   ULONG i;
00410   ULONG ChunkSize;
00411   PVOID Context = NULL;
00412   LARGE_INTEGER Offset;
00413   ULONG FatLength;
00414 
00415   ChunkSize = CACHEPAGESIZE(DeviceExt);
00416   FatLength = (DeviceExt->FatInfo.NumberOfClusters + 2);
00417 
00418   for (i = 2; i < FatLength; )
00419   {
00420     Offset.QuadPart = ROUND_DOWN(i * 4, ChunkSize);
00421     if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00422     {
00423       DPRINT1("CcMapData(Offset %x, Length %d) failed\n", (ULONG)Offset.QuadPart, ChunkSize);
00424       return STATUS_UNSUCCESSFUL;
00425     }
00426     Block = (PULONG)((ULONG_PTR)BaseAddress + (i * 4) % ChunkSize);
00427     BlockEnd = (PULONG)((ULONG_PTR)BaseAddress + ChunkSize);
00428 
00429     /* Now process the whole block */
00430     while (Block < BlockEnd && i < FatLength)
00431     {
00432       if ((*Block & 0x0fffffff) == 0)
00433         ulCount++;
00434       Block++;
00435       i++;
00436     }
00437 
00438     CcUnpinData(Context);
00439   }
00440 
00441   DeviceExt->AvailableClusters = ulCount;
00442   DeviceExt->AvailableClustersValid = TRUE;
00443 
00444   return(STATUS_SUCCESS);
00445 }
00446 
00447 NTSTATUS
00448 CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
00449                 PLARGE_INTEGER Clusters)
00450 {
00451   NTSTATUS Status = STATUS_SUCCESS;
00452   ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
00453   if (!DeviceExt->AvailableClustersValid)
00454   {
00455     if (DeviceExt->FatInfo.FatType == FAT12)
00456       Status = FAT12CountAvailableClusters(DeviceExt);
00457     else if (DeviceExt->FatInfo.FatType == FAT16 || DeviceExt->FatInfo.FatType == FATX16)
00458       Status = FAT16CountAvailableClusters(DeviceExt);
00459     else
00460       Status = FAT32CountAvailableClusters(DeviceExt);
00461     }
00462   Clusters->QuadPart = DeviceExt->AvailableClusters;
00463   ExReleaseResourceLite (&DeviceExt->FatResource);
00464 
00465   return Status;
00466 }
00467 
00468 
00469 
00470 
00471 
00472 NTSTATUS
00473 FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
00474           ULONG ClusterToWrite,
00475           ULONG NewValue,
00476           PULONG OldValue)
00477 /*
00478  * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
00479  */
00480 {
00481   ULONG FATOffset;
00482   PUCHAR CBlock;
00483   PVOID BaseAddress;
00484   PVOID Context;
00485   LARGE_INTEGER Offset;
00486 
00487   Offset.QuadPart = 0;
00488   if(!CcPinRead(DeviceExt->FATFileObject, &Offset, DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector, 1, &Context, &BaseAddress))
00489   {
00490     return STATUS_UNSUCCESSFUL;
00491   }
00492   CBlock = (PUCHAR)BaseAddress;
00493 
00494   FATOffset = (ClusterToWrite * 12) / 8;
00495   DPRINT("Writing 0x%x for 0x%x at 0x%x\n",
00496       NewValue, ClusterToWrite, FATOffset);
00497   if ((ClusterToWrite % 2) == 0)
00498     {
00499       *OldValue = CBlock[FATOffset] + ((CBlock[FATOffset + 1] & 0x0f) << 8);
00500       CBlock[FATOffset] = (UCHAR)NewValue;
00501       CBlock[FATOffset + 1] &= 0xf0;
00502       CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
00503     }
00504   else
00505     {
00506       *OldValue = (CBlock[FATOffset] >> 4) + (CBlock[FATOffset + 1] << 4);
00507       CBlock[FATOffset] &= 0x0f;
00508       CBlock[FATOffset] |= (NewValue & 0xf) << 4;
00509       CBlock[FATOffset + 1] = (UCHAR)(NewValue >> 4);
00510     }
00511   /* Write the changed FAT sector(s) to disk */
00512   CcSetDirtyPinnedData(Context, NULL);
00513   CcUnpinData(Context);
00514   return(STATUS_SUCCESS);
00515 }
00516 
00517 NTSTATUS
00518 FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
00519           ULONG ClusterToWrite,
00520           ULONG NewValue,
00521           PULONG OldValue)
00522 /*
00523  * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
00524  */
00525 {
00526   PVOID BaseAddress;
00527   ULONG FATOffset;
00528   ULONG ChunkSize;
00529   PVOID Context;
00530   LARGE_INTEGER Offset;
00531   PUSHORT Cluster;
00532 
00533   ChunkSize = CACHEPAGESIZE(DeviceExt);
00534   FATOffset = ClusterToWrite * 2;
00535   Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
00536   if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00537   {
00538     return STATUS_UNSUCCESSFUL;
00539   }
00540   DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
00541          ClusterToWrite);
00542   Cluster = ((PUSHORT)((char*)BaseAddress + (FATOffset % ChunkSize)));
00543   *OldValue = *Cluster;
00544   *Cluster = (USHORT)NewValue;
00545   CcSetDirtyPinnedData(Context, NULL);
00546   CcUnpinData(Context);
00547   return(STATUS_SUCCESS);
00548 }
00549 
00550 NTSTATUS
00551 FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
00552           ULONG ClusterToWrite,
00553           ULONG NewValue,
00554           PULONG OldValue)
00555 /*
00556  * FUNCTION: Writes a cluster to the FAT32 physical tables
00557  */
00558 {
00559   PVOID BaseAddress;
00560   ULONG FATOffset;
00561   ULONG ChunkSize;
00562   PVOID Context;
00563   LARGE_INTEGER Offset;
00564   PULONG Cluster;
00565 
00566   ChunkSize = CACHEPAGESIZE(DeviceExt);
00567 
00568   FATOffset = (ClusterToWrite * 4);
00569   Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
00570   if(!CcPinRead(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
00571   {
00572     return STATUS_UNSUCCESSFUL;
00573   }
00574   DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
00575          ClusterToWrite);
00576   Cluster = ((PULONG)((char*)BaseAddress + (FATOffset % ChunkSize)));
00577   *OldValue = *Cluster & 0x0fffffff;
00578   *Cluster = (*Cluster & 0xf0000000) | (NewValue & 0x0fffffff);
00579 
00580   CcSetDirtyPinnedData(Context, NULL);
00581   CcUnpinData(Context);
00582 
00583   return(STATUS_SUCCESS);
00584 }
00585 
00586 
00587 NTSTATUS
00588 WriteCluster(PDEVICE_EXTENSION DeviceExt,
00589          ULONG ClusterToWrite,
00590          ULONG NewValue)
00591 /*
00592  * FUNCTION: Write a changed FAT entry
00593  */
00594 {
00595   NTSTATUS Status;
00596   ULONG OldValue;
00597   ExAcquireResourceExclusiveLite (&DeviceExt->FatResource, TRUE);
00598   Status = DeviceExt->WriteCluster(DeviceExt, ClusterToWrite, NewValue, &OldValue);
00599   if (DeviceExt->AvailableClustersValid)
00600   {
00601       if (OldValue && NewValue == 0)
00602         InterlockedIncrement((PLONG)&DeviceExt->AvailableClusters);
00603       else if (OldValue == 0 && NewValue)
00604         InterlockedDecrement((PLONG)&DeviceExt->AvailableClusters);
00605   }
00606   ExReleaseResourceLite(&DeviceExt->FatResource);
00607   return(Status);
00608 }
00609 
00610 ULONGLONG
00611 ClusterToSector(PDEVICE_EXTENSION DeviceExt,
00612         ULONG Cluster)
00613 /*
00614  * FUNCTION: Converts the cluster number to a sector number for this physical
00615  *           device
00616  */
00617 {
00618   return DeviceExt->FatInfo.dataStart +
00619     ((ULONGLONG)(Cluster - 2) * DeviceExt->FatInfo.SectorsPerCluster);
00620 
00621 }
00622 
00623 NTSTATUS
00624 GetNextCluster(PDEVICE_EXTENSION DeviceExt,
00625            ULONG CurrentCluster,
00626            PULONG NextCluster)
00627 /*
00628  * FUNCTION: Retrieve the next cluster depending on the FAT type
00629  */
00630 {
00631   NTSTATUS Status;
00632 
00633   DPRINT ("GetNextCluster(DeviceExt %p, CurrentCluster %x)\n",
00634       DeviceExt, CurrentCluster);
00635 
00636   if (CurrentCluster == 0)
00637      return(STATUS_INVALID_PARAMETER);
00638 
00639   ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
00640   Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
00641   ExReleaseResourceLite(&DeviceExt->FatResource);
00642 
00643   return(Status);
00644 }
00645 
00646 NTSTATUS
00647 GetNextClusterExtend(PDEVICE_EXTENSION DeviceExt,
00648                  ULONG CurrentCluster,
00649                  PULONG NextCluster)
00650 /*
00651  * FUNCTION: Retrieve the next cluster depending on the FAT type
00652  */
00653 {
00654   NTSTATUS Status;
00655 
00656   DPRINT ("GetNextClusterExtend(DeviceExt %p, CurrentCluster %x)\n",
00657       DeviceExt, CurrentCluster);
00658 
00659   ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
00660   /*
00661    * If the file hasn't any clusters allocated then we need special
00662    * handling
00663    */
00664   if (CurrentCluster == 0)
00665   {
00666     ULONG NewCluster;
00667 
00668     Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
00669     if (!NT_SUCCESS(Status))
00670     {
00671       ExReleaseResourceLite(&DeviceExt->FatResource);
00672       return Status;
00673     }
00674 
00675     *NextCluster = NewCluster;
00676     ExReleaseResourceLite(&DeviceExt->FatResource);
00677     return(STATUS_SUCCESS);
00678   }
00679 
00680   Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
00681 
00682   if ((*NextCluster) == 0xFFFFFFFF)
00683   {
00684      ULONG NewCluster;
00685 
00686      /* We are after last existing cluster, we must add one to file */
00687      /* Firstly, find the next available open allocation unit and
00688         mark it as end of file */
00689      Status = DeviceExt->FindAndMarkAvailableCluster(DeviceExt, &NewCluster);
00690      if (!NT_SUCCESS(Status))
00691      {
00692         ExReleaseResourceLite(&DeviceExt->FatResource);
00693         return Status;
00694      }
00695 
00696      /* Now, write the AU of the LastCluster with the value of the newly
00697         found AU */
00698      WriteCluster(DeviceExt, CurrentCluster, NewCluster);
00699      *NextCluster = NewCluster;
00700   }
00701 
00702   ExReleaseResourceLite(&DeviceExt->FatResource);
00703 
00704   return(Status);
00705 }
00706 
00707 /* EOF */

Generated on Sat May 19 2012 04:16:56 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.