Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfat.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
1.7.6.1
|