1999-12-11 21:14:49 +00:00
|
|
|
/*
|
2001-10-10 22:16:46 +00:00
|
|
|
* $Id: fat.c,v 1.33 2001/10/10 22:16:46 hbirr Exp $
|
1999-12-11 21:14:49 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
|
|
|
* FILE: services/fs/vfat/fat.c
|
|
|
|
* PURPOSE: VFAT Filesystem
|
|
|
|
* PROGRAMMER: Jason Filby (jasonfilby@yahoo.com)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2000-02-22 02:02:08 +00:00
|
|
|
#include <ddk/ntddk.h>
|
1999-12-11 21:14:49 +00:00
|
|
|
#include <wchar.h>
|
2001-01-13 18:38:09 +00:00
|
|
|
#include <ntos/minmax.h>
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2001-04-29 21:08:14 +00:00
|
|
|
#define NDEBUG
|
2000-06-29 23:35:53 +00:00
|
|
|
#include <debug.h>
|
1999-12-11 21:14:49 +00:00
|
|
|
|
|
|
|
#include "vfat.h"
|
|
|
|
|
2001-07-13 10:31:14 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
|
|
|
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
|
|
|
|
|
|
|
|
#define CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
|
|
|
|
(pDeviceExt)->BytesPerCluster : PAGESIZE)
|
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2001-01-12 21:00:08 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG CurrentCluster,
|
|
|
|
PULONG NextCluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
|
|
|
|
* disk read
|
|
|
|
*/
|
|
|
|
{
|
2001-02-06 00:41:19 +00:00
|
|
|
PVOID BaseAddress;
|
2001-01-12 21:00:08 +00:00
|
|
|
NTSTATUS Status;
|
2001-02-06 00:41:19 +00:00
|
|
|
ULONG FATOffset;
|
2001-07-20 08:00:21 +00:00
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
|
|
|
FATOffset = CurrentCluster * sizeof(ULONG);
|
|
|
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-10-03 18:23:02 +00:00
|
|
|
CurrentCluster = (*(PULONG)(BaseAddress + (FATOffset % ChunkSize))) & 0x0fffffff;
|
2000-12-29 23:17:12 +00:00
|
|
|
if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
|
1999-12-11 21:14:49 +00:00
|
|
|
CurrentCluster = 0xffffffff;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-01-12 21:00:08 +00:00
|
|
|
*NextCluster = CurrentCluster;
|
|
|
|
return (STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-12 21:00:08 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG CurrentCluster,
|
|
|
|
PULONG NextCluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
2001-03-01 07:48:17 +00:00
|
|
|
* FUNCTION: Retrieve the next FAT16 cluster from the FAT table
|
1999-12-11 21:14:49 +00:00
|
|
|
*/
|
|
|
|
{
|
2001-01-08 02:14:06 +00:00
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG FATOffset;
|
2001-07-13 10:31:14 +00:00
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
2001-10-03 18:23:02 +00:00
|
|
|
|
2001-07-13 10:31:14 +00:00
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
2001-10-10 22:16:46 +00:00
|
|
|
FATOffset = CurrentCluster * 2;
|
|
|
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-07-13 10:31:14 +00:00
|
|
|
CurrentCluster = *((PUSHORT)(BaseAddress + (FATOffset % ChunkSize)));
|
2000-12-29 23:17:12 +00:00
|
|
|
if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
|
2001-01-12 21:00:08 +00:00
|
|
|
CurrentCluster = 0xffffffff;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-01-12 21:00:08 +00:00
|
|
|
*NextCluster = CurrentCluster;
|
|
|
|
return (STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-12 21:00:08 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG CurrentCluster,
|
|
|
|
PULONG NextCluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
2001-01-12 21:00:08 +00:00
|
|
|
* FUNCTION: Retrieve the next FAT12 cluster from the FAT table
|
1999-12-11 21:14:49 +00:00
|
|
|
*/
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
PUCHAR CBlock;
|
|
|
|
ULONG FATOffset;
|
|
|
|
ULONG Entry;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BaseAddress;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
|
|
|
|
*NextCluster = 0;
|
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
Offset.QuadPart = 0;
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
CBlock = (PUCHAR)BaseAddress;
|
2001-10-10 22:16:46 +00:00
|
|
|
|
2001-04-26 04:01:54 +00:00
|
|
|
FATOffset = (CurrentCluster * 12) / 8; /* first byte containing value */
|
2000-12-29 23:17:12 +00:00
|
|
|
if ((CurrentCluster % 2) == 0)
|
|
|
|
{
|
2001-01-16 09:55:02 +00:00
|
|
|
Entry = CBlock[FATOffset];
|
|
|
|
Entry |= ((CBlock[FATOffset+1] & 0xf)<<8);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-01-16 09:55:02 +00:00
|
|
|
Entry = (CBlock[FATOffset] >> 4);
|
|
|
|
Entry |= (CBlock[FATOffset+1] << 4);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-03-01 07:48:17 +00:00
|
|
|
// DPRINT("Entry %x\n",Entry);
|
2000-12-29 23:17:12 +00:00
|
|
|
if (Entry >= 0xff8 && Entry <= 0xfff)
|
1999-12-11 21:14:49 +00:00
|
|
|
Entry = 0xffffffff;
|
2001-03-01 07:48:17 +00:00
|
|
|
// DPRINT("Returning %x\n",Entry);
|
2001-01-12 21:00:08 +00:00
|
|
|
*NextCluster = Entry;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-08-14 08:06:26 +00:00
|
|
|
// return Entry == 0xffffffff ? STATUS_END_OF_FILE : STATUS_SUCCESS;
|
|
|
|
return STATUS_SUCCESS;
|
2001-01-12 21:00:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PULONG Cluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Finds the first available cluster in a FAT16 table
|
|
|
|
*/
|
|
|
|
{
|
2001-01-14 15:05:53 +00:00
|
|
|
ULONG FatLength;
|
2001-01-12 21:00:08 +00:00
|
|
|
ULONG i;
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS Status;
|
2001-01-12 21:00:08 +00:00
|
|
|
PVOID BaseAddress;
|
2001-07-13 10:31:14 +00:00
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context = 0;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
|
2001-07-13 10:31:14 +00:00
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
2001-07-20 08:00:21 +00:00
|
|
|
FatLength = (((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2)*2;
|
2001-01-14 15:05:53 +00:00
|
|
|
*Cluster = 0;
|
|
|
|
|
2001-01-16 09:55:02 +00:00
|
|
|
for (i = 2; i < FatLength; i+=2)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
if ((i % ChunkSize) == 0 || Context ==0)
|
2001-01-12 21:00:08 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
|
|
|
if (Context != NULL)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-01-12 21:00:08 +00:00
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
|
|
|
|
if (*((PUSHORT)(BaseAddress + (i % ChunkSize))) == 0)
|
2001-01-12 21:00:08 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
DPRINT("Found available cluster 0x%x\n", i / 2);
|
2001-01-14 15:05:53 +00:00
|
|
|
*Cluster = i / 2;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-01-14 15:05:53 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-01-12 21:00:08 +00:00
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
CcUnpinData(Context);
|
2001-01-14 15:05:53 +00:00
|
|
|
return(STATUS_DISK_FULL);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Finds the first available cluster in a FAT12 table
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG FATOffset;
|
|
|
|
ULONG Entry;
|
2001-01-16 09:55:02 +00:00
|
|
|
PUCHAR CBlock;
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG i;
|
2001-01-16 09:55:02 +00:00
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
2001-03-01 07:48:17 +00:00
|
|
|
ULONG numberofclusters;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
|
2001-01-16 09:55:02 +00:00
|
|
|
*Cluster = 0;
|
2001-10-10 22:16:46 +00:00
|
|
|
Offset.QuadPart = 0;
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
CBlock = (PUCHAR)BaseAddress;
|
|
|
|
|
2001-03-01 07:48:17 +00:00
|
|
|
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
|
|
|
|
|
|
|
for (i = 2; i < numberofclusters; i++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
|
|
|
FATOffset = (i * 12) / 8;
|
|
|
|
if ((i % 2) == 0)
|
|
|
|
{
|
|
|
|
Entry = CBlock[FATOffset];
|
|
|
|
Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Entry = (CBlock[FATOffset] >> 4);
|
|
|
|
Entry |= (CBlock[FATOffset + 1] << 4);
|
|
|
|
}
|
|
|
|
if (Entry == 0)
|
2001-01-16 09:55:02 +00:00
|
|
|
{
|
2001-01-16 15:43:42 +00:00
|
|
|
DPRINT("Found available cluster 0x%x\n", i);
|
2001-01-16 09:55:02 +00:00
|
|
|
*Cluster = i;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-01-16 23:22:03 +00:00
|
|
|
return(STATUS_SUCCESS);
|
2001-01-16 09:55:02 +00:00
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-01-16 09:55:02 +00:00
|
|
|
return (STATUS_DISK_FULL);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
|
|
|
FAT32FindAvailableCluster (PDEVICE_EXTENSION DeviceExt, PULONG Cluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Finds the first available cluster in a FAT32 table
|
|
|
|
*/
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
ULONG FatLength;
|
|
|
|
ULONG i;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BaseAddress;
|
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context = NULL;
|
|
|
|
LARGE_INTEGER Offset;
|
2001-07-20 08:00:21 +00:00
|
|
|
|
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
|
|
|
FatLength = (((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2)*4;
|
|
|
|
|
|
|
|
*Cluster = 0;
|
|
|
|
|
|
|
|
for (i = 4; i < FatLength; i+=4)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
if ((i % ChunkSize) == 0 || Context == NULL)
|
2001-07-20 08:00:21 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
Offset.QuadPart = ROUND_DOWN(i, ChunkSize);
|
|
|
|
if (Context != NULL)
|
|
|
|
{
|
|
|
|
CcUnpinData(Context);
|
|
|
|
}
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-07-20 08:00:21 +00:00
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
if ((*((PULONG)(BaseAddress + (/*(FatStart +*/ i/*)*/ % ChunkSize))) & 0x0fffffff) == 0)
|
2001-07-20 08:00:21 +00:00
|
|
|
{
|
2001-10-07 08:58:29 +00:00
|
|
|
DPRINT("Found available cluster 0x%x\n", i / 4);
|
2001-07-20 08:00:21 +00:00
|
|
|
*Cluster = i / 4;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2001-07-20 08:00:21 +00:00
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
CcUnpinData(Context);
|
2001-01-14 15:05:53 +00:00
|
|
|
return (STATUS_DISK_FULL);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-03-01 07:48:17 +00:00
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
NTSTATUS
|
|
|
|
FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PLARGE_INTEGER Clusters)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Counts free cluster in a FAT12 table
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG FATOffset;
|
|
|
|
ULONG Entry;
|
2001-03-01 07:48:17 +00:00
|
|
|
PUCHAR CBlock;
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG ulCount = 0;
|
|
|
|
ULONG i;
|
2001-03-01 07:48:17 +00:00
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG numberofclusters;
|
2001-10-10 22:16:46 +00:00
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
PVOID Context;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
|
|
|
ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE);
|
2001-10-10 22:16:46 +00:00
|
|
|
Offset.QuadPart = 0;
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
ExReleaseResourceLite (&DeviceExt->FatResource);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-03-01 07:48:17 +00:00
|
|
|
CBlock = (PUCHAR)BaseAddress;
|
|
|
|
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
2001-10-10 22:16:46 +00:00
|
|
|
|
2001-03-01 07:48:17 +00:00
|
|
|
for (i = 2; i < numberofclusters; i++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
|
|
|
FATOffset = (i * 12) / 8;
|
|
|
|
if ((i % 2) == 0)
|
|
|
|
{
|
|
|
|
Entry = CBlock[FATOffset];
|
|
|
|
Entry |= ((CBlock[FATOffset + 1] & 0xf) << 8);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Entry = (CBlock[FATOffset] >> 4);
|
|
|
|
Entry |= (CBlock[FATOffset + 1] << 4);
|
|
|
|
}
|
|
|
|
if (Entry == 0)
|
|
|
|
ulCount++;
|
|
|
|
}
|
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
CcUnpinData(Context);
|
2000-12-29 23:17:12 +00:00
|
|
|
ExReleaseResourceLite (&DeviceExt->FatResource);
|
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
Clusters->QuadPart = ulCount;
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
NTSTATUS
|
|
|
|
FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PLARGE_INTEGER Clusters)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Counts free clusters in a FAT16 table
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
PUSHORT Block;
|
|
|
|
ULONG ulCount = 0;
|
|
|
|
ULONG i;
|
2001-07-20 08:00:21 +00:00
|
|
|
ULONG numberofclusters;
|
|
|
|
ULONG numberofsectors;
|
|
|
|
ULONG sector;
|
|
|
|
ULONG forto;
|
|
|
|
NTSTATUS Status;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
|
|
|
ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE);
|
2001-07-20 08:00:21 +00:00
|
|
|
Block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
|
|
|
numberofsectors = (numberofclusters + 255) / 256;
|
|
|
|
numberofclusters %= 256;
|
|
|
|
|
|
|
|
for (sector = 0; sector < numberofsectors; sector++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
|
|
|
DeviceExt->FATStart + sector,
|
|
|
|
1,
|
|
|
|
(PUCHAR)Block);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePool(Block);
|
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
|
|
return(Status);
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
if (sector == numberofsectors - 1)
|
|
|
|
forto = numberofclusters;
|
|
|
|
else
|
|
|
|
forto = 256;
|
|
|
|
|
|
|
|
for (i = 0; i < forto; i++)
|
|
|
|
{
|
|
|
|
if (Block[i] == 0)
|
|
|
|
ulCount++;
|
|
|
|
}
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
ExReleaseResourceLite (&DeviceExt->FatResource);
|
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
Clusters->QuadPart = ulCount;
|
2001-10-10 22:16:46 +00:00
|
|
|
ExFreePool(Block);
|
2001-06-14 10:02:59 +00:00
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
2001-07-20 08:00:21 +00:00
|
|
|
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
NTSTATUS
|
|
|
|
FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
PLARGE_INTEGER Clusters)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Counts free clusters in a FAT32 table
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG sector;
|
|
|
|
PULONG Block;
|
|
|
|
ULONG ulCount = 0;
|
2001-03-01 07:48:17 +00:00
|
|
|
ULONG i,forto;
|
|
|
|
ULONG numberofclusters;
|
2001-07-20 08:00:21 +00:00
|
|
|
ULONG numberofsectors;
|
2001-06-14 10:02:59 +00:00
|
|
|
NTSTATUS Status;
|
2000-12-29 23:17:12 +00:00
|
|
|
|
|
|
|
ExAcquireResourceSharedLite (&DeviceExt->FatResource, TRUE);
|
|
|
|
|
|
|
|
Block = ExAllocatePool (NonPagedPool, BLOCKSIZE);
|
2001-03-01 07:48:17 +00:00
|
|
|
|
|
|
|
numberofclusters = ((DeviceExt->Boot->Sectors ? DeviceExt->Boot->Sectors : DeviceExt->Boot->SectorsHuge)-DeviceExt->dataStart)/DeviceExt->Boot->SectorsPerCluster+2;
|
2001-07-20 08:00:21 +00:00
|
|
|
numberofsectors = (numberofclusters +127) / 128;
|
2001-03-01 07:48:17 +00:00
|
|
|
numberofclusters %= 128;
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
for (sector = 0; sector < numberofsectors; sector++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-06-14 10:02:59 +00:00
|
|
|
Status = VfatReadSectors(DeviceExt->StorageDevice,
|
|
|
|
(ULONG) (DeviceExt->FATStart + sector), 1,
|
|
|
|
(UCHAR *) Block);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
ExFreePool(Block);
|
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
|
|
return(Status);
|
|
|
|
}
|
2000-12-29 23:17:12 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
if (sector == numberofsectors - 1)
|
|
|
|
forto=numberofclusters;
|
|
|
|
else
|
|
|
|
forto=128;
|
2001-03-01 07:48:17 +00:00
|
|
|
for (i = 0; i < forto; i++)
|
2000-12-29 23:17:12 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
if ((Block[i] & 0x0fffffff) == 0)
|
2000-12-29 23:17:12 +00:00
|
|
|
ulCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ExFreePool (Block);
|
|
|
|
ExReleaseResourceLite (&DeviceExt->FatResource);
|
2001-06-14 10:02:59 +00:00
|
|
|
|
|
|
|
Clusters->QuadPart = ulCount;
|
|
|
|
|
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
2001-06-14 10:02:59 +00:00
|
|
|
FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG ClusterToWrite,
|
|
|
|
ULONG NewValue)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG FATsector;
|
|
|
|
ULONG FATOffset;
|
2001-01-16 09:55:02 +00:00
|
|
|
PUCHAR CBlock;
|
2000-12-29 23:17:12 +00:00
|
|
|
int i;
|
2001-01-16 09:55:02 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID BaseAddress;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
|
|
|
|
Offset.QuadPart = 0;
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, DeviceExt->Boot->FATSectors * BLOCKSIZE, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
CBlock = (PUCHAR)BaseAddress;
|
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
FATOffset = (ClusterToWrite * 12) / 8;
|
2001-01-16 15:43:42 +00:00
|
|
|
DPRINT("Writing 0x%x for 0x%x at 0x%x\n",
|
2001-01-16 09:55:02 +00:00
|
|
|
NewValue, ClusterToWrite, FATOffset);
|
2000-12-29 23:17:12 +00:00
|
|
|
if ((ClusterToWrite % 2) == 0)
|
|
|
|
{
|
|
|
|
CBlock[FATOffset] = NewValue;
|
|
|
|
CBlock[FATOffset + 1] &= 0xf0;
|
|
|
|
CBlock[FATOffset + 1] |= (NewValue & 0xf00) >> 8;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CBlock[FATOffset] &= 0x0f;
|
|
|
|
CBlock[FATOffset] |= (NewValue & 0xf) << 4;
|
|
|
|
CBlock[FATOffset + 1] = NewValue >> 4;
|
|
|
|
}
|
|
|
|
/* Write the changed FAT sector(s) to disk */
|
|
|
|
FATsector = FATOffset / BLOCKSIZE;
|
2001-10-10 22:16:46 +00:00
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
2001-01-16 09:55:02 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
2001-06-14 10:02:59 +00:00
|
|
|
FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG ClusterToWrite,
|
|
|
|
ULONG NewValue)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
|
|
|
|
*/
|
|
|
|
{
|
2001-01-14 15:05:53 +00:00
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG FATOffset;
|
|
|
|
ULONG i;
|
2001-07-13 10:31:14 +00:00
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
|
|
|
|
2001-07-13 10:31:14 +00:00
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
2001-10-10 22:16:46 +00:00
|
|
|
FATOffset = ClusterToWrite * 2;
|
|
|
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
2001-01-16 09:55:02 +00:00
|
|
|
ClusterToWrite);
|
2001-10-10 22:16:46 +00:00
|
|
|
*((PUSHORT)(BaseAddress + (FATOffset % ChunkSize))) = NewValue;
|
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
2001-07-20 08:00:21 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-06-14 10:02:59 +00:00
|
|
|
NTSTATUS
|
|
|
|
FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG ClusterToWrite,
|
|
|
|
ULONG NewValue)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Writes a cluster to the FAT32 physical tables
|
|
|
|
*/
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
PVOID BaseAddress;
|
|
|
|
NTSTATUS Status;
|
|
|
|
ULONG FATOffset;
|
|
|
|
ULONG i;
|
|
|
|
ULONG ChunkSize;
|
2001-10-10 22:16:46 +00:00
|
|
|
PVOID Context;
|
|
|
|
LARGE_INTEGER Offset;
|
2001-07-20 08:00:21 +00:00
|
|
|
|
|
|
|
ChunkSize = CACHEPAGESIZE(DeviceExt);
|
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
FATOffset = (ClusterToWrite * 4);
|
|
|
|
Offset.QuadPart = ROUND_DOWN(FATOffset, ChunkSize);
|
|
|
|
if(!CcMapData(DeviceExt->FATFileObject, &Offset, ChunkSize, 1, &Context, &BaseAddress))
|
|
|
|
{
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
DPRINT("Writing 0x%x for offset 0x%x 0x%x\n", NewValue, FATOffset,
|
|
|
|
ClusterToWrite);
|
|
|
|
*((PULONG)(BaseAddress + (FATOffset % ChunkSize))) = NewValue & 0x0fffffff;
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
CcSetDirtyPinnedData(Context, NULL);
|
|
|
|
CcUnpinData(Context);
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
DPRINT("DeviceExt->Boot->FATSectors %d\n",
|
2001-07-20 08:00:21 +00:00
|
|
|
((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32);
|
2001-06-14 10:02:59 +00:00
|
|
|
return(STATUS_SUCCESS);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
2001-06-14 10:02:59 +00:00
|
|
|
WriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG ClusterToWrite,
|
|
|
|
ULONG NewValue)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Write a changed FAT entry
|
|
|
|
*/
|
|
|
|
{
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
if (DeviceExt->FatType == FAT16)
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
Status = FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
|
|
|
else if (DeviceExt->FatType == FAT32)
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
Status = FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
Status = FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-01-14 15:05:53 +00:00
|
|
|
return(Status);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG
|
2001-07-20 08:00:21 +00:00
|
|
|
ClusterToSector(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG Cluster)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Converts the cluster number to a sector number for this physical
|
|
|
|
* device
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
return DeviceExt->dataStart +
|
|
|
|
((Cluster - 2) * DeviceExt->Boot->SectorsPerCluster);
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
NTSTATUS
|
2001-06-14 10:02:59 +00:00
|
|
|
VfatRawReadCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG FirstCluster,
|
|
|
|
PVOID Buffer,
|
2001-10-10 22:16:46 +00:00
|
|
|
ULONG Cluster,
|
|
|
|
ULONG Count)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
2001-10-10 22:16:46 +00:00
|
|
|
* FUNCTION: Load one ore more continus clusters from the physical device
|
1999-12-11 21:14:49 +00:00
|
|
|
*/
|
|
|
|
{
|
|
|
|
|
2001-01-14 15:05:53 +00:00
|
|
|
if (FirstCluster == 1)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
return VfatReadSectors(DeviceExt->StorageDevice, Cluster,
|
|
|
|
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
|
|
|
}
|
2001-01-14 15:05:53 +00:00
|
|
|
else
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ULONG Sector;
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
Sector = ClusterToSector(DeviceExt, Cluster);
|
|
|
|
return VfatReadSectors(DeviceExt->StorageDevice, Sector,
|
|
|
|
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
|
|
|
}
|
1999-12-11 21:14:49 +00:00
|
|
|
}
|
|
|
|
|
2001-01-13 18:38:09 +00:00
|
|
|
NTSTATUS
|
2001-06-14 10:02:59 +00:00
|
|
|
VfatRawWriteCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG FirstCluster,
|
|
|
|
PVOID Buffer,
|
2001-10-10 22:16:46 +00:00
|
|
|
ULONG Cluster,
|
|
|
|
ULONG Count)
|
1999-12-11 21:14:49 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Write a cluster to the physical device
|
|
|
|
*/
|
|
|
|
{
|
2000-12-29 23:17:12 +00:00
|
|
|
ULONG Sector;
|
2001-01-13 18:38:09 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
DPRINT("VfatWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
|
|
|
|
DeviceExt, Buffer, Cluster);
|
1999-12-11 21:14:49 +00:00
|
|
|
|
2001-01-16 09:55:02 +00:00
|
|
|
if (FirstCluster == 1)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
Status = VfatWriteSectors(DeviceExt->StorageDevice, Cluster,
|
|
|
|
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
else
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
Sector = ClusterToSector(DeviceExt, Cluster);
|
2001-10-03 18:23:02 +00:00
|
|
|
|
2001-10-10 22:16:46 +00:00
|
|
|
Status = VfatWriteSectors(DeviceExt->StorageDevice, Sector,
|
|
|
|
DeviceExt->Boot->SectorsPerCluster * Count, Buffer);
|
|
|
|
}
|
2001-01-13 18:38:09 +00:00
|
|
|
return(Status);
|
2000-12-29 23:17:12 +00:00
|
|
|
}
|
2001-01-13 18:38:09 +00:00
|
|
|
|
2001-01-16 09:55:02 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
GetNextCluster(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG CurrentCluster,
|
|
|
|
PULONG NextCluster,
|
|
|
|
BOOLEAN Extend)
|
2001-01-16 09:55:02 +00:00
|
|
|
/*
|
|
|
|
* FUNCTION: Retrieve the next cluster depending on the FAT type
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2001-10-03 18:23:02 +00:00
|
|
|
|
2001-03-01 07:48:17 +00:00
|
|
|
// DPRINT ("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
|
|
|
|
// DeviceExt, CurrentCluster);
|
2001-10-03 18:23:02 +00:00
|
|
|
|
2001-10-07 08:58:29 +00:00
|
|
|
if (!Extend)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
else
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
|
|
|
|
}
|
2001-10-03 18:23:02 +00:00
|
|
|
|
2001-01-16 09:55:02 +00:00
|
|
|
/*
|
|
|
|
* If the file hasn't any clusters allocated then we need special
|
|
|
|
* handling
|
|
|
|
*/
|
|
|
|
if (CurrentCluster == 0 && Extend)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ULONG NewCluster;
|
|
|
|
|
|
|
|
if (DeviceExt->FatType == FAT16)
|
|
|
|
{
|
|
|
|
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2001-10-07 08:58:29 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-01-16 09:55:02 +00:00
|
|
|
return(Status);
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (DeviceExt->FatType == FAT32)
|
|
|
|
{
|
|
|
|
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-03-01 07:48:17 +00:00
|
|
|
{
|
2001-10-07 08:58:29 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-03-01 07:48:17 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-01-16 09:55:02 +00:00
|
|
|
{
|
2001-10-07 08:58:29 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-01-16 09:55:02 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
/* Mark the new AU as the EOF */
|
|
|
|
WriteCluster (DeviceExt, NewCluster, 0xFFFFFFFF);
|
|
|
|
*NextCluster = NewCluster;
|
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
else if (CurrentCluster == 0)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
|
|
|
|
if (DeviceExt->FatType == FAT16)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
Status = Fat16GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
else if (DeviceExt->FatType == FAT32)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
Status = Fat32GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
else
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
Status = Fat12GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
if (Extend && (*NextCluster) == 0xFFFFFFFF)
|
2001-10-10 22:16:46 +00:00
|
|
|
{
|
|
|
|
ULONG NewCluster;
|
|
|
|
|
|
|
|
/* We are after last existing cluster, we must add one to file */
|
|
|
|
/* Firstly, find the next available open allocation unit */
|
|
|
|
if (DeviceExt->FatType == FAT16)
|
|
|
|
{
|
|
|
|
Status = FAT16FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-01-16 09:55:02 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-01-16 09:55:02 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
else if (DeviceExt->FatType == FAT32)
|
|
|
|
{
|
|
|
|
Status = FAT32FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-03-01 07:48:17 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-03-01 07:48:17 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Status = FAT12FindAvailableCluster(DeviceExt, &NewCluster);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2001-01-16 09:55:02 +00:00
|
|
|
{
|
2001-10-10 22:16:46 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-01-16 09:55:02 +00:00
|
|
|
return(Status);
|
|
|
|
}
|
2001-10-10 22:16:46 +00:00
|
|
|
}
|
|
|
|
/* Mark the new AU as the EOF */
|
|
|
|
WriteCluster(DeviceExt, NewCluster, 0xFFFFFFFF);
|
|
|
|
/* Now, write the AU of the LastCluster with the value of the newly
|
|
|
|
found AU */
|
|
|
|
WriteCluster(DeviceExt, CurrentCluster, NewCluster);
|
|
|
|
*NextCluster = NewCluster;
|
|
|
|
}
|
2001-01-16 09:55:02 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
ExReleaseResourceLite(&DeviceExt->FatResource);
|
2001-01-16 09:55:02 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
return(Status);
|
2001-01-16 09:55:02 +00:00
|
|
|
}
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
|
2001-03-02 15:59:16 +00:00
|
|
|
NTSTATUS
|
2001-07-20 08:00:21 +00:00
|
|
|
GetNextSector(PDEVICE_EXTENSION DeviceExt,
|
|
|
|
ULONG CurrentSector,
|
|
|
|
PULONG NextSector,
|
|
|
|
BOOLEAN Extend)
|
2001-03-02 15:59:16 +00:00
|
|
|
/* Some functions don't have access to the cluster they're really reading from.
|
|
|
|
Maybe this is a dirty solution, but it will allow them to handle fragmentation. */
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
DPRINT("GetNextSector(DeviceExt %x, CurrentSector %x)\n",
|
|
|
|
DeviceExt,
|
|
|
|
CurrentSector);
|
2001-03-02 15:59:16 +00:00
|
|
|
if (CurrentSector<DeviceExt->dataStart || ((CurrentSector - DeviceExt->dataStart + 1) % DeviceExt -> Boot -> SectorsPerCluster))
|
|
|
|
/* Basically, if the next sequential sector would be on a cluster border, then we'll need to check in the FAT */
|
|
|
|
{
|
2001-07-20 08:00:21 +00:00
|
|
|
(*NextSector)=CurrentSector+1;
|
|
|
|
return (STATUS_SUCCESS);
|
2001-03-02 15:59:16 +00:00
|
|
|
}
|
|
|
|
else
|
2001-07-20 08:00:21 +00:00
|
|
|
{
|
|
|
|
CurrentSector = (CurrentSector - DeviceExt->dataStart) / DeviceExt -> Boot -> SectorsPerCluster + 2;
|
2001-03-02 15:59:16 +00:00
|
|
|
|
2001-07-20 08:00:21 +00:00
|
|
|
Status = GetNextCluster(DeviceExt, CurrentSector, NextSector, Extend);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
if ((*NextSector) == 0 || (*NextSector) == 0xffffffff)
|
|
|
|
{
|
|
|
|
/* The caller wants to know a sector. These FAT codes don't correspond to any sector. */
|
|
|
|
return(STATUS_UNSUCCESSFUL);
|
|
|
|
}
|
|
|
|
|
|
|
|
(*NextSector) = ClusterToSector(DeviceExt,(*NextSector));
|
|
|
|
return(STATUS_SUCCESS);
|
|
|
|
}
|
2001-03-06 17:28:25 +00:00
|
|
|
}
|
2001-07-13 10:31:14 +00:00
|
|
|
|
|
|
|
/* EOF */
|