ReactOS 0.4.16-dev-522-gb68104a
fat.c File Reference
#include <freeldr.h>
#include <debug.h>
Include dependency graph for fat.c:

Go to the source code of this file.

Classes

struct  _FAT_VOLUME_INFO
 
struct  _DIRECTORY_BUFFER
 

Macros

#define FAT_IS_END_CLUSTER(clnumber)
 
#define TAG_FAT_CHAIN   'CtaT'
 
#define TAG_FAT_FILE   'FtaF'
 
#define TAG_FAT_VOLUME   'VtaF'
 
#define TAG_FAT_BUFFER   'BtaF'
 
#define TAG_FAT_CACHE   'HtaF'
 
#define FAT_MAX_CACHE_SIZE   (256 * 1024)
 

Typedefs

typedef struct _FAT_VOLUME_INFO FAT_VOLUME_INFO
 
typedef struct _DIRECTORY_BUFFER DIRECTORY_BUFFER
 
typedef struct _DIRECTORY_BUFFERPDIRECTORY_BUFFER
 

Functions

 DBG_DEFAULT_CHANNEL (FILESYSTEM)
 
ULONG FatDetermineFatType (PFAT_BOOTSECTOR FatBootSector, ULONGLONG PartitionSectorCount)
 
PVOID FatBufferDirectory (PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG *EntryCountPointer, BOOLEAN RootDirectory)
 
BOOLEAN FatSearchDirectoryBufferForFile (PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
 
ARC_STATUS FatLookupFile (PFAT_VOLUME_INFO Volume, PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
 
void FatParseShortFileName (PCHAR Buffer, PDIRENTRY DirEntry)
 
static BOOLEAN FatGetFatEntry (PFAT_VOLUME_INFO Volume, UINT32 Cluster, PUINT32 ClusterPointer)
 
static ULONG FatCountClustersInChain (PFAT_VOLUME_INFO Volume, UINT32 StartCluster)
 
static BOOLEAN FatReadClusterChain (PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32 NumberOfClusters, PVOID Buffer, PUINT32 LastClusterNumber)
 
BOOLEAN FatReadPartialCluster (PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
 
BOOLEAN FatReadVolumeSectors (PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
 
VOID FatSwapFatBootSector (PFAT_BOOTSECTOR Obj)
 
VOID FatSwapFat32BootSector (PFAT32_BOOTSECTOR Obj)
 
VOID FatSwapFatXBootSector (PFATX_BOOTSECTOR Obj)
 
VOID FatSwapDirEntry (PDIRENTRY Obj)
 
VOID FatSwapLFNDirEntry (PLFN_DIRENTRY Obj)
 
VOID FatSwapFatXDirEntry (PFATX_DIRENTRY Obj)
 
BOOLEAN FatOpenVolume (PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONGLONG PartitionSectorCount)
 
static BOOLEAN FatXSearchDirectoryBufferForFile (PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
 
static PUCHAR FatGetFatSector (PFAT_VOLUME_INFO Volume, UINT32 FatSectorNumber)
 Reads 1-4 sectors from FAT using the cache.
 
static BOOLEAN FatReadAdjacentClusters (PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32 MaxClusters, PVOID Buffer, PUINT32 ClustersRead, PUINT32 LastClusterNumber)
 
static BOOLEAN FatReadFile (PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG *BytesRead, PVOID Buffer)
 
ARC_STATUS FatClose (ULONG FileId)
 
ARC_STATUS FatGetFileInformation (ULONG FileId, FILEINFORMATION *Information)
 
ARC_STATUS FatOpen (CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
 
ARC_STATUS FatRead (ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
 
ARC_STATUS FatSeek (ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
 
const DEVVTBLFatMount (ULONG DeviceId)
 

Variables

PFAT_VOLUME_INFO FatVolumes [MAX_FDS]
 
LIST_ENTRY DirectoryBufferListHead = {&DirectoryBufferListHead, &DirectoryBufferListHead}
 
const DEVVTBL FatFuncTable
 
const DEVVTBL FatXFuncTable
 

Macro Definition Documentation

◆ FAT_IS_END_CLUSTER

#define FAT_IS_END_CLUSTER (   clnumber)
Value:
(((Volume->FatType == FAT12) && (clnumber >= 0xff8)) || \
((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (clnumber >= 0xfff8)) || \
((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (clnumber >= 0x0ffffff8)))
#define FAT32
Definition: fat.h:169
#define FATX16
Definition: fat.h:170
#define FATX32
Definition: fat.h:171
#define FAT12
Definition: fat.h:167
#define FAT16
Definition: fat.h:168
UNICODE_STRING Volume
Definition: fltkernel.h:1172

Definition at line 26 of file fat.c.

◆ FAT_MAX_CACHE_SIZE

#define FAT_MAX_CACHE_SIZE   (256 * 1024)

Definition at line 37 of file fat.c.

◆ TAG_FAT_BUFFER

#define TAG_FAT_BUFFER   'BtaF'

Definition at line 34 of file fat.c.

◆ TAG_FAT_CACHE

#define TAG_FAT_CACHE   'HtaF'

Definition at line 35 of file fat.c.

◆ TAG_FAT_CHAIN

#define TAG_FAT_CHAIN   'CtaT'

Definition at line 31 of file fat.c.

◆ TAG_FAT_FILE

#define TAG_FAT_FILE   'FtaF'

Definition at line 32 of file fat.c.

◆ TAG_FAT_VOLUME

#define TAG_FAT_VOLUME   'VtaF'

Definition at line 33 of file fat.c.

Typedef Documentation

◆ DIRECTORY_BUFFER

◆ FAT_VOLUME_INFO

◆ PDIRECTORY_BUFFER

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( FILESYSTEM  )

◆ FatBufferDirectory()

PVOID FatBufferDirectory ( PFAT_VOLUME_INFO  Volume,
ULONG  DirectoryStartCluster,
ULONG EntryCountPointer,
BOOLEAN  RootDirectory 
)

Definition at line 419 of file fat.c.

420{
421 PDIRECTORY_BUFFER DirectoryBuffer;
423
424 TRACE("FatBufferDirectory() DirectoryStartCluster = %d RootDirectory = %s\n", DirectoryStartCluster, (RootDirectory ? "TRUE" : "FALSE"));
425
426 /*
427 * For FAT32, the root directory is nothing special. We can treat it the same
428 * as a subdirectory.
429 */
430 if (RootDirectory && Volume->FatType == FAT32)
431 {
432 DirectoryStartCluster = Volume->RootDirStartCluster;
434 }
435
436 /* Search the list for a match */
439 Entry = Entry->Flink)
440 {
441 DirectoryBuffer = CONTAINING_RECORD(Entry, DIRECTORY_BUFFER, Link);
442
443 /* Check if it matches */
444 if ((DirectoryBuffer->Volume == Volume) &&
445 (DirectoryBuffer->DirectoryStartCluster == DirectoryStartCluster))
446 {
447 TRACE("Found cached buffer\n");
448 *DirectorySize = DirectoryBuffer->DirectorySize;
449 return DirectoryBuffer->Data;
450 }
451 }
452
453 //
454 // Calculate the size of the directory
455 //
456 if (RootDirectory)
457 {
458 *DirectorySize = Volume->RootDirSectors * Volume->BytesPerSector;
459 }
460 else
461 {
462 *DirectorySize = FatCountClustersInChain(Volume, DirectoryStartCluster) * Volume->SectorsPerCluster * Volume->BytesPerSector;
463 }
464
465 //
466 // Attempt to allocate memory for directory buffer
467 //
468 TRACE("Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize);
469 DirectoryBuffer = FrLdrTempAlloc(*DirectorySize + sizeof(DIRECTORY_BUFFER),
471
472 if (DirectoryBuffer == NULL)
473 {
474 return NULL;
475 }
476
477 //
478 // Now read directory contents into DirectoryBuffer
479 //
480 if (RootDirectory)
481 {
482 if (!FatReadVolumeSectors(Volume, Volume->RootDirSectorStart, Volume->RootDirSectors, DirectoryBuffer->Data))
483 {
484 FrLdrTempFree(DirectoryBuffer, TAG_FAT_BUFFER);
485 return NULL;
486 }
487 }
488 else
489 {
490 if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer->Data, NULL))
491 {
492 FrLdrTempFree(DirectoryBuffer, TAG_FAT_BUFFER);
493 return NULL;
494 }
495 }
496
497 /* Enqueue it in the list */
498 DirectoryBuffer->Volume = Volume;
499 DirectoryBuffer->DirectoryStartCluster = DirectoryStartCluster;
500 DirectoryBuffer->DirectorySize = *DirectorySize;
501 InsertTailList(&DirectoryBufferListHead, &DirectoryBuffer->Link);
502
503 return DirectoryBuffer->Data;
504}
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:188
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:197
static BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32 NumberOfClusters, PVOID Buffer, PUINT32 LastClusterNumber)
Definition: fat.c:1128
static ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, UINT32 StartCluster)
Definition: fat.c:1044
BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: fat.c:1363
#define TAG_FAT_BUFFER
Definition: fat.c:34
LIST_ENTRY DirectoryBufferListHead
Definition: fat.c:417
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define InsertTailList(ListHead, Entry)
#define TRACE(s)
Definition: solgame.cpp:4
base of all file and directory entries
Definition: entries.h:83
LIST_ENTRY Link
Definition: fat.c:410
PVOID Volume
Definition: fat.c:411
ULONG DirectorySize
Definition: fat.c:413
ULONG DirectoryStartCluster
Definition: fat.c:412
UCHAR Data[]
Definition: fat.c:414
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
static int Link(const char **args)
Definition: vfdcmd.c:2414

Referenced by FatLookupFile().

◆ FatClose()

ARC_STATUS FatClose ( ULONG  FileId)

Definition at line 1397 of file fat.c.

1398{
1400
1402
1403 return ESUCCESS;
1404}
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:632
#define TAG_FAT_FILE
Definition: fat.c:32
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ ESUCCESS
Definition: arc.h:32

◆ FatCountClustersInChain()

static ULONG FatCountClustersInChain ( PFAT_VOLUME_INFO  Volume,
UINT32  StartCluster 
)
static

Definition at line 1044 of file fat.c.

1045{
1046 ULONG ClusterCount = 0;
1047
1048 TRACE("FatCountClustersInChain() StartCluster = %d\n", StartCluster);
1049
1050 while (1)
1051 {
1052 //
1053 // If end of chain then break out of our cluster counting loop
1054 //
1055 if (FAT_IS_END_CLUSTER(StartCluster))
1056 {
1057 break;
1058 }
1059
1060 //
1061 // Increment count
1062 //
1063 ClusterCount++;
1064
1065 //
1066 // Get next cluster
1067 //
1068 if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
1069 {
1070 return 0;
1071 }
1072 }
1073
1074 TRACE("FatCountClustersInChain() ClusterCount = %d\n", ClusterCount);
1075
1076 return ClusterCount;
1077}
static BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, UINT32 Cluster, PUINT32 ClusterPointer)
Definition: fat.c:954
#define FAT_IS_END_CLUSTER(clnumber)
Definition: fat.c:26
uint32_t ULONG
Definition: typedefs.h:59

Referenced by FatBufferDirectory().

◆ FatDetermineFatType()

ULONG FatDetermineFatType ( PFAT_BOOTSECTOR  FatBootSector,
ULONGLONG  PartitionSectorCount 
)

Definition at line 353 of file fat.c.

354{
355 ULONG RootDirSectors;
356 ULONG DataSectorCount;
357 ULONG SectorsPerFat;
358 ULONG TotalSectors;
359 ULONG CountOfClusters;
360 PFAT32_BOOTSECTOR Fat32BootSector = (PFAT32_BOOTSECTOR)FatBootSector;
361 PFATX_BOOTSECTOR FatXBootSector = (PFATX_BOOTSECTOR)FatBootSector;
362
363 if (0 == strncmp(FatXBootSector->FileSystemType, "FATX", 4))
364 {
365 CountOfClusters = (ULONG)(PartitionSectorCount / FatXBootSector->SectorsPerCluster);
366 if (CountOfClusters < 65525)
367 {
368 /* Volume is FATX16 */
369 return FATX16;
370 }
371 else
372 {
373 /* Volume is FAT32 */
374 return FATX32;
375 }
376 }
377 else
378 {
379 RootDirSectors = ((SWAPW(FatBootSector->RootDirEntries) * 32) + (SWAPW(FatBootSector->BytesPerSector) - 1)) / SWAPW(FatBootSector->BytesPerSector);
380 SectorsPerFat = SWAPW(FatBootSector->SectorsPerFat) ? SWAPW(FatBootSector->SectorsPerFat) : SWAPD(Fat32BootSector->SectorsPerFatBig);
381 TotalSectors = SWAPW(FatBootSector->TotalSectors) ? SWAPW(FatBootSector->TotalSectors) : SWAPD(FatBootSector->TotalSectorsBig);
382 DataSectorCount = TotalSectors - (SWAPW(FatBootSector->ReservedSectors) + (FatBootSector->NumberOfFats * SectorsPerFat) + RootDirSectors);
383
384//mjl
385 if (FatBootSector->SectorsPerCluster == 0)
386 CountOfClusters = 0;
387 else
388 CountOfClusters = DataSectorCount / FatBootSector->SectorsPerCluster;
389
390 if (CountOfClusters < 4085)
391 {
392 /* Volume is FAT12 */
393 return FAT12;
394 }
395 else if (CountOfClusters < 65525)
396 {
397 /* Volume is FAT16 */
398 return FAT16;
399 }
400 else
401 {
402 /* Volume is FAT32 */
403 return FAT32;
404 }
405 }
406}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
ULONG PartitionSectorCount
Definition: partition.c:39
struct _FATX_BOOTSECTOR * PFATX_BOOTSECTOR
#define SWAPD(x)
Definition: bytesex.h:7
#define SWAPW(x)
Definition: bytesex.h:8
struct _FAT32_BOOTSECTOR * PFAT32_BOOTSECTOR
ULONG SectorsPerCluster
Definition: fat.h:92
CHAR FileSystemType[4]
Definition: fat.h:90
USHORT TotalSectors
Definition: fsutil.c:45
UCHAR NumberOfFats
Definition: fsutil.c:43
USHORT SectorsPerFat
Definition: fsutil.c:47
USHORT ReservedSectors
Definition: fsutil.c:42
USHORT BytesPerSector
Definition: fsutil.c:40
USHORT RootDirEntries
Definition: fsutil.c:44
UCHAR SectorsPerCluster
Definition: fsutil.c:41

Referenced by FatOpenVolume().

◆ FatGetFatEntry()

static BOOLEAN FatGetFatEntry ( PFAT_VOLUME_INFO  Volume,
UINT32  Cluster,
PUINT32  ClusterPointer 
)
static

Definition at line 954 of file fat.c.

955{
956 UINT32 FatOffset, ThisFatSecNum, ThisFatEntOffset, fat;
958
959 TRACE("FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster);
960
961 switch(Volume->FatType)
962 {
963 case FAT12:
964
965 FatOffset = Cluster + (Cluster / 2);
966 ThisFatSecNum = FatOffset / Volume->BytesPerSector;
967 ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
968
969 TRACE("FatOffset: %d\n", FatOffset);
970 TRACE("ThisFatSecNum: %d\n", ThisFatSecNum);
971 TRACE("ThisFatEntOffset: %d\n", ThisFatEntOffset);
972
973 // The cluster pointer can span within two sectors, but the FatGetFatSector function
974 // reads 4 sectors most times, except when we are at the edge of FAT cache
975 // and/or FAT region on the disk. For FAT12 the whole FAT would be cached so
976 // there will be no situation when the first sector is at the end of the cache
977 // and the next one is in the beginning
978
979 ReadBuffer = FatGetFatSector(Volume, ThisFatSecNum);
980 if (!ReadBuffer)
981 {
982 return FALSE;
983 }
984
985 fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
986 fat = SWAPW(fat);
987 if (Cluster & 0x0001)
988 fat = fat >> 4; /* Cluster number is ODD */
989 else
990 fat = fat & 0x0FFF; /* Cluster number is EVEN */
991
992 break;
993
994 case FAT16:
995 case FATX16:
996
997 FatOffset = (Cluster * 2);
998 ThisFatSecNum = FatOffset / Volume->BytesPerSector;
999 ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
1000
1001 ReadBuffer = FatGetFatSector(Volume, ThisFatSecNum);
1002 if (!ReadBuffer)
1003 {
1004 return FALSE;
1005 }
1006
1007 fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
1008 fat = SWAPW(fat);
1009
1010 break;
1011
1012 case FAT32:
1013 case FATX32:
1014
1015 FatOffset = (Cluster * 4);
1016 ThisFatSecNum = FatOffset / Volume->BytesPerSector;
1017 ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
1018
1019 ReadBuffer = FatGetFatSector(Volume, ThisFatSecNum);
1020 if (!ReadBuffer)
1021 {
1022 return FALSE;
1023 }
1024
1025 // Get the fat entry
1026 fat = (*((ULONG *) (ReadBuffer + ThisFatEntOffset))) & 0x0FFFFFFF;
1027 fat = SWAPD(fat);
1028
1029 break;
1030
1031 default:
1032 ERR("Unknown FAT type %d\n", Volume->FatType);
1033 return FALSE;
1034 }
1035
1036 TRACE("FAT entry is 0x%x.\n", fat);
1037
1038 *ClusterPointer = fat;
1039
1040 return TRUE;
1041}
unsigned int UINT32
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
#define ERR(fmt,...)
Definition: precomp.h:57
static PUCHAR FatGetFatSector(PFAT_VOLUME_INFO Volume, UINT32 FatSectorNumber)
Reads 1-4 sectors from FAT using the cache.
Definition: fat.c:916
#define TRUE
Definition: types.h:120
static unsigned char * fat
Definition: mkdosfs.c:542
unsigned short USHORT
Definition: pedump.c:61
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by FatCountClustersInChain(), FatReadAdjacentClusters(), FatReadFile(), and FatSeek().

◆ FatGetFatSector()

static PUCHAR FatGetFatSector ( PFAT_VOLUME_INFO  Volume,
UINT32  FatSectorNumber 
)
static

Reads 1-4 sectors from FAT using the cache.

Definition at line 916 of file fat.c.

917{
918 UINT32 SectorNumAbsolute = Volume->ActiveFatSectorStart + FatSectorNumber;
919 UINT32 CacheIndex = FatSectorNumber % Volume->FatCacheSize;
920
921 ASSERT(FatSectorNumber < Volume->SectorsPerFat);
922
923 // cache miss
924 if (Volume->FatCacheIndex[CacheIndex] != SectorNumAbsolute)
925 {
926 UINT32 SectorsToRead = min(Volume->FatCacheSize - CacheIndex, min(Volume->SectorsPerFat - SectorNumAbsolute, 4));
927 UINT8 i;
928
929 if (!FatReadVolumeSectors(Volume, SectorNumAbsolute, SectorsToRead, &Volume->FatCache[CacheIndex * Volume->BytesPerSector]))
930 {
931 return NULL;
932 }
933
934 for (i = 0; i < SectorsToRead; i++)
935 {
936 Volume->FatCacheIndex[CacheIndex + i] = SectorNumAbsolute + i;
937 }
938
939 TRACE("FAT cache miss: read sector 0x%x from disk\n", SectorNumAbsolute);
940 }
941 else
942 {
943 TRACE("FAT cache hit: sector 0x%x present\n", SectorNumAbsolute);
944 }
945
946 return &Volume->FatCache[CacheIndex * Volume->BytesPerSector];
947}
unsigned char UINT8
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55

Referenced by FatGetFatEntry().

◆ FatGetFileInformation()

ARC_STATUS FatGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)

Definition at line 1406 of file fat.c.

1407{
1409
1411 Information->EndingAddress.LowPart = FileHandle->FileSize;
1412 Information->CurrentAddress.LowPart = FileHandle->FilePointer;
1413
1414 TRACE("FatGetFileInformation(%lu) -> FileSize = %lu, FilePointer = 0x%lx\n",
1415 FileId, Information->EndingAddress.LowPart, Information->CurrentAddress.LowPart);
1416
1417 return ESUCCESS;
1418}
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049

◆ FatLookupFile()

ARC_STATUS FatLookupFile ( PFAT_VOLUME_INFO  Volume,
PCSTR  FileName,
PFAT_FILE_INFO  FatFileInfoPointer 
)

Definition at line 774 of file fat.c.

775{
776 UINT32 i;
777 ULONG NumberOfPathParts;
778 CHAR PathPart[261];
779 PVOID DirectoryBuffer;
780 ULONG DirectoryStartCluster = 0;
781 ULONG DirectorySize;
782 FAT_FILE_INFO FatFileInfo;
783
784 TRACE("FatLookupFile() FileName = %s\n", FileName);
785
786 RtlZeroMemory(FatFileInfoPointer, sizeof(FAT_FILE_INFO));
787
788 /* Skip leading path separator, if any */
789 if (*FileName == '\\' || *FileName == '/')
790 ++FileName;
791 //
792 // Figure out how many sub-directories we are nested in
793 //
794 NumberOfPathParts = FsGetNumPathParts(FileName);
795
796 //
797 // Loop once for each part
798 //
799 for (i=0; i<NumberOfPathParts; i++)
800 {
801 //
802 // Get first path part
803 //
805
806 //
807 // Advance to the next part of the path
808 //
809 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
810 {
811 }
812 FileName++;
813
814 //
815 // Buffer the directory contents
816 //
817 DirectoryBuffer = FatBufferDirectory(Volume, DirectoryStartCluster, &DirectorySize, (i == 0) );
818 if (DirectoryBuffer == NULL)
819 {
820 return ENOMEM;
821 }
822
823 //
824 // Search for file name in directory
825 //
826 if (ISFATX(Volume->FatType))
827 {
828 if (!FatXSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
829 {
830 return ENOENT;
831 }
832 }
833 else
834 {
835 if (!FatSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
836 {
837 return ENOENT;
838 }
839 }
840
841 //
842 // If we have another sub-directory to go then
843 // grab the start cluster and free the fat chain array
844 //
845 if ((i+1) < NumberOfPathParts)
846 {
847 //
848 // Check if current entry is a directory
849 //
850 if (!(FatFileInfo.Attributes & ATTR_DIRECTORY))
851 {
852 return ENOTDIR;
853 }
854 DirectoryStartCluster = FatFileInfo.StartCluster;
855 }
856 }
857
858 RtlCopyMemory(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
859
860 return ESUCCESS;
861}
#define ENOENT
Definition: acclib.h:79
#define ENOMEM
Definition: acclib.h:84
#define ISFATX(FT)
Definition: fat.h:173
#define ATTR_DIRECTORY
Definition: fat.h:163
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:540
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:568
BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:506
PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG *EntryCountPointer, BOOLEAN RootDirectory)
Definition: fat.c:419
static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:711
#define ENOTDIR
Definition: errno.h:26
struct _FileName FileName
Definition: fatprocs.h:897
UCHAR Attributes
Definition: fat.h:155
ULONG StartCluster
Definition: fat.h:154
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
char CHAR
Definition: xmlstorage.h:175

Referenced by FatOpen().

◆ FatMount()

const DEVVTBL * FatMount ( ULONG  DeviceId)

Definition at line 1563 of file fat.c.

1564{
1566 UCHAR Buffer[512];
1572 ULONG Count;
1575
1576 TRACE("Enter FatMount(%lu)\n", DeviceId);
1577
1578 //
1579 // Allocate data for volume information
1580 //
1582 if (!Volume)
1583 return NULL;
1585
1586 //
1587 // Read the BootSector
1588 //
1589 Position.QuadPart = 0;
1590 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1591 if (Status != ESUCCESS)
1592 {
1594 return NULL;
1595 }
1596 Status = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count);
1597 if (Status != ESUCCESS || Count != sizeof(Buffer))
1598 {
1600 return NULL;
1601 }
1602
1603 //
1604 // Check if BootSector is valid. If no, return early
1605 //
1606 if (!RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) &&
1607 !RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) &&
1608 !RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) &&
1609 !RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4))
1610 {
1612 return NULL;
1613 }
1614
1615 //
1616 // Determine sector count
1617 //
1619 if (Status != ESUCCESS)
1620 {
1622 return NULL;
1623 }
1624 SectorCount.QuadPart = (FileInformation.EndingAddress.QuadPart - FileInformation.StartingAddress.QuadPart);
1625 SectorCount.QuadPart /= SECTOR_SIZE;
1626
1627 //
1628 // Keep device id
1629 //
1630 Volume->DeviceId = DeviceId;
1631
1632 //
1633 // Really open the volume
1634 //
1635 if (!FatOpenVolume(Volume, BootSector, SectorCount.QuadPart))
1636 {
1638 return NULL;
1639 }
1640
1641 //
1642 // Remember FAT volume information
1643 //
1644 FatVolumes[DeviceId] = Volume;
1645
1646 //
1647 // Return success
1648 //
1649 TRACE("FatMount(%lu) success\n", DeviceId);
1650 return (ISFATX(Volume->FatType) ? &FatXFuncTable : &FatFuncTable);
1651}
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:462
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
#define SECTOR_SIZE
Definition: fs.h:22
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
#define TAG_FAT_VOLUME
Definition: fat.c:33
const DEVVTBL FatXFuncTable
Definition: fat.c:1553
BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONGLONG PartitionSectorCount)
Definition: fat.c:138
PFAT_VOLUME_INFO FatVolumes[MAX_FDS]
Definition: fat.c:58
const DEVVTBL FatFuncTable
Definition: fat.c:1543
Definition: bufpool.h:45
Status
Definition: gdiplustypes.h:25
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
static OUT PIO_STATUS_BLOCK OUT PVOID FileInformation
Definition: pipe.c:75
int Count
Definition: noreturn.cpp:7
ULONG SectorCount
Definition: part_xbox.c:31
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
struct _FAT_BOOTSECTOR * PFAT_BOOTSECTOR
static COORD Position
Definition: mouse.c:34
unsigned char UCHAR
Definition: xmlstorage.h:181

◆ FatOpen()

ARC_STATUS FatOpen ( CHAR Path,
OPENMODE  OpenMode,
ULONG FileId 
)

Definition at line 1420 of file fat.c.

1421{
1422 PFAT_VOLUME_INFO FatVolume;
1423 FAT_FILE_INFO TempFileInfo;
1425 ULONG DeviceId;
1428
1429 if (OpenMode != OpenReadOnly && OpenMode != OpenDirectory)
1430 return EACCES;
1431
1432 DeviceId = FsGetDeviceId(*FileId);
1433 FatVolume = FatVolumes[DeviceId];
1434
1435 TRACE("FatOpen() FileName = %s\n", Path);
1436
1437 RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo));
1438 Status = FatLookupFile(FatVolume, Path, &TempFileInfo);
1439 if (Status != ESUCCESS)
1440 return ENOENT;
1441
1442 //
1443 // Check if caller opened what he expected (dir vs file)
1444 //
1445 IsDirectory = (TempFileInfo.Attributes & ATTR_DIRECTORY) != 0;
1446 if (IsDirectory && OpenMode != OpenDirectory)
1447 return EISDIR;
1448 else if (!IsDirectory && OpenMode != OpenReadOnly)
1449 return ENOTDIR;
1450
1452 if (!FileHandle)
1453 return ENOMEM;
1454
1455 RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO));
1456 FileHandle->Volume = FatVolume;
1457
1459 return ESUCCESS;
1460}
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
#define EACCES
Definition: acclib.h:85
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:625
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:639
ARC_STATUS FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:774
#define EISDIR
Definition: errno.h:27
#define IsDirectory(Fcb)
Definition: ext2fs.h:283
@ OpenDirectory
Definition: arc.h:73
@ OpenReadOnly
Definition: arc.h:65
PVOID Volume
Definition: fltmgrint.h:141

◆ FatOpenVolume()

BOOLEAN FatOpenVolume ( PFAT_VOLUME_INFO  Volume,
PFAT_BOOTSECTOR  BootSector,
ULONGLONG  PartitionSectorCount 
)

Definition at line 138 of file fat.c.

139{
140 char ErrMsg[80];
141 ULONG FatSize, i;
142 PFAT_BOOTSECTOR FatVolumeBootSector;
143 PFAT32_BOOTSECTOR Fat32VolumeBootSector;
144 PFATX_BOOTSECTOR FatXVolumeBootSector;
145
146 TRACE("FatOpenVolume() DeviceId = %d\n", Volume->DeviceId);
147
148 //
149 // Allocate the memory to hold the boot sector
150 //
151 FatVolumeBootSector = (PFAT_BOOTSECTOR)BootSector;
152 Fat32VolumeBootSector = (PFAT32_BOOTSECTOR)BootSector;
153 FatXVolumeBootSector = (PFATX_BOOTSECTOR)BootSector;
154
155 // Get the FAT type
156 Volume->FatType = FatDetermineFatType(FatVolumeBootSector, PartitionSectorCount);
157
158 // Dump boot sector (and swap it for big endian systems)
159 TRACE("Dumping boot sector:\n");
160 if (ISFATX(Volume->FatType))
161 {
162 FatSwapFatXBootSector(FatXVolumeBootSector);
163 TRACE("sizeof(FATX_BOOTSECTOR) = 0x%x.\n", sizeof(FATX_BOOTSECTOR));
164
165 TRACE("FileSystemType: %c%c%c%c.\n", FatXVolumeBootSector->FileSystemType[0], FatXVolumeBootSector->FileSystemType[1], FatXVolumeBootSector->FileSystemType[2], FatXVolumeBootSector->FileSystemType[3]);
166 TRACE("VolumeSerialNumber: 0x%x\n", FatXVolumeBootSector->VolumeSerialNumber);
167 TRACE("SectorsPerCluster: %d\n", FatXVolumeBootSector->SectorsPerCluster);
168 TRACE("NumberOfFats: %d\n", FatXVolumeBootSector->NumberOfFats);
169 TRACE("Unknown: 0x%x\n", FatXVolumeBootSector->Unknown);
170
171 TRACE("FatType %s\n", Volume->FatType == FATX16 ? "FATX16" : "FATX32");
172
173 }
174 else if (Volume->FatType == FAT32)
175 {
176 FatSwapFat32BootSector(Fat32VolumeBootSector);
177 TRACE("sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR));
178
179 TRACE("JumpBoot: 0x%x 0x%x 0x%x\n", Fat32VolumeBootSector->JumpBoot[0], Fat32VolumeBootSector->JumpBoot[1], Fat32VolumeBootSector->JumpBoot[2]);
180 TRACE("OemName: %c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->OemName[0], Fat32VolumeBootSector->OemName[1], Fat32VolumeBootSector->OemName[2], Fat32VolumeBootSector->OemName[3], Fat32VolumeBootSector->OemName[4], Fat32VolumeBootSector->OemName[5], Fat32VolumeBootSector->OemName[6], Fat32VolumeBootSector->OemName[7]);
181 TRACE("BytesPerSector: %d\n", Fat32VolumeBootSector->BytesPerSector);
182 TRACE("SectorsPerCluster: %d\n", Fat32VolumeBootSector->SectorsPerCluster);
183 TRACE("ReservedSectors: %d\n", Fat32VolumeBootSector->ReservedSectors);
184 TRACE("NumberOfFats: %d\n", Fat32VolumeBootSector->NumberOfFats);
185 TRACE("RootDirEntries: %d\n", Fat32VolumeBootSector->RootDirEntries);
186 TRACE("TotalSectors: %d\n", Fat32VolumeBootSector->TotalSectors);
187 TRACE("MediaDescriptor: 0x%x\n", Fat32VolumeBootSector->MediaDescriptor);
188 TRACE("SectorsPerFat: %d\n", Fat32VolumeBootSector->SectorsPerFat);
189 TRACE("SectorsPerTrack: %d\n", Fat32VolumeBootSector->SectorsPerTrack);
190 TRACE("NumberOfHeads: %d\n", Fat32VolumeBootSector->NumberOfHeads);
191 TRACE("HiddenSectors: %d\n", Fat32VolumeBootSector->HiddenSectors);
192 TRACE("TotalSectorsBig: %d\n", Fat32VolumeBootSector->TotalSectorsBig);
193 TRACE("SectorsPerFatBig: %d\n", Fat32VolumeBootSector->SectorsPerFatBig);
194 TRACE("ExtendedFlags: 0x%x\n", Fat32VolumeBootSector->ExtendedFlags);
195 TRACE("FileSystemVersion: 0x%x\n", Fat32VolumeBootSector->FileSystemVersion);
196 TRACE("RootDirStartCluster: %d\n", Fat32VolumeBootSector->RootDirStartCluster);
197 TRACE("FsInfo: %d\n", Fat32VolumeBootSector->FsInfo);
198 TRACE("BackupBootSector: %d\n", Fat32VolumeBootSector->BackupBootSector);
199 TRACE("Reserved: 0x%x\n", Fat32VolumeBootSector->Reserved);
200 TRACE("DriveNumber: 0x%x\n", Fat32VolumeBootSector->DriveNumber);
201 TRACE("Reserved1: 0x%x\n", Fat32VolumeBootSector->Reserved1);
202 TRACE("BootSignature: 0x%x\n", Fat32VolumeBootSector->BootSignature);
203 TRACE("VolumeSerialNumber: 0x%x\n", Fat32VolumeBootSector->VolumeSerialNumber);
204 TRACE("VolumeLabel: %c%c%c%c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->VolumeLabel[0], Fat32VolumeBootSector->VolumeLabel[1], Fat32VolumeBootSector->VolumeLabel[2], Fat32VolumeBootSector->VolumeLabel[3], Fat32VolumeBootSector->VolumeLabel[4], Fat32VolumeBootSector->VolumeLabel[5], Fat32VolumeBootSector->VolumeLabel[6], Fat32VolumeBootSector->VolumeLabel[7], Fat32VolumeBootSector->VolumeLabel[8], Fat32VolumeBootSector->VolumeLabel[9], Fat32VolumeBootSector->VolumeLabel[10]);
205 TRACE("FileSystemType: %c%c%c%c%c%c%c%c\n", Fat32VolumeBootSector->FileSystemType[0], Fat32VolumeBootSector->FileSystemType[1], Fat32VolumeBootSector->FileSystemType[2], Fat32VolumeBootSector->FileSystemType[3], Fat32VolumeBootSector->FileSystemType[4], Fat32VolumeBootSector->FileSystemType[5], Fat32VolumeBootSector->FileSystemType[6], Fat32VolumeBootSector->FileSystemType[7]);
206 TRACE("BootSectorMagic: 0x%x\n", Fat32VolumeBootSector->BootSectorMagic);
207 }
208 else
209 {
210 FatSwapFatBootSector(FatVolumeBootSector);
211 TRACE("sizeof(FAT_BOOTSECTOR) = 0x%x.\n", sizeof(FAT_BOOTSECTOR));
212
213 TRACE("JumpBoot: 0x%x 0x%x 0x%x\n", FatVolumeBootSector->JumpBoot[0], FatVolumeBootSector->JumpBoot[1], FatVolumeBootSector->JumpBoot[2]);
214 TRACE("OemName: %c%c%c%c%c%c%c%c\n", FatVolumeBootSector->OemName[0], FatVolumeBootSector->OemName[1], FatVolumeBootSector->OemName[2], FatVolumeBootSector->OemName[3], FatVolumeBootSector->OemName[4], FatVolumeBootSector->OemName[5], FatVolumeBootSector->OemName[6], FatVolumeBootSector->OemName[7]);
215 TRACE("BytesPerSector: %d\n", FatVolumeBootSector->BytesPerSector);
216 TRACE("SectorsPerCluster: %d\n", FatVolumeBootSector->SectorsPerCluster);
217 TRACE("ReservedSectors: %d\n", FatVolumeBootSector->ReservedSectors);
218 TRACE("NumberOfFats: %d\n", FatVolumeBootSector->NumberOfFats);
219 TRACE("RootDirEntries: %d\n", FatVolumeBootSector->RootDirEntries);
220 TRACE("TotalSectors: %d\n", FatVolumeBootSector->TotalSectors);
221 TRACE("MediaDescriptor: 0x%x\n", FatVolumeBootSector->MediaDescriptor);
222 TRACE("SectorsPerFat: %d\n", FatVolumeBootSector->SectorsPerFat);
223 TRACE("SectorsPerTrack: %d\n", FatVolumeBootSector->SectorsPerTrack);
224 TRACE("NumberOfHeads: %d\n", FatVolumeBootSector->NumberOfHeads);
225 TRACE("HiddenSectors: %d\n", FatVolumeBootSector->HiddenSectors);
226 TRACE("TotalSectorsBig: %d\n", FatVolumeBootSector->TotalSectorsBig);
227 TRACE("DriveNumber: 0x%x\n", FatVolumeBootSector->DriveNumber);
228 TRACE("Reserved1: 0x%x\n", FatVolumeBootSector->Reserved1);
229 TRACE("BootSignature: 0x%x\n", FatVolumeBootSector->BootSignature);
230 TRACE("VolumeSerialNumber: 0x%x\n", FatVolumeBootSector->VolumeSerialNumber);
231 TRACE("VolumeLabel: %c%c%c%c%c%c%c%c%c%c%c\n", FatVolumeBootSector->VolumeLabel[0], FatVolumeBootSector->VolumeLabel[1], FatVolumeBootSector->VolumeLabel[2], FatVolumeBootSector->VolumeLabel[3], FatVolumeBootSector->VolumeLabel[4], FatVolumeBootSector->VolumeLabel[5], FatVolumeBootSector->VolumeLabel[6], FatVolumeBootSector->VolumeLabel[7], FatVolumeBootSector->VolumeLabel[8], FatVolumeBootSector->VolumeLabel[9], FatVolumeBootSector->VolumeLabel[10]);
232 TRACE("FileSystemType: %c%c%c%c%c%c%c%c\n", FatVolumeBootSector->FileSystemType[0], FatVolumeBootSector->FileSystemType[1], FatVolumeBootSector->FileSystemType[2], FatVolumeBootSector->FileSystemType[3], FatVolumeBootSector->FileSystemType[4], FatVolumeBootSector->FileSystemType[5], FatVolumeBootSector->FileSystemType[6], FatVolumeBootSector->FileSystemType[7]);
233 TRACE("BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic);
234 }
235
236 //
237 // Check the boot sector magic
238 //
239 if (! ISFATX(Volume->FatType) && FatVolumeBootSector->BootSectorMagic != 0xaa55)
240 {
241 sprintf(ErrMsg, "Invalid boot sector magic (expected 0xaa55 found 0x%x)",
242 FatVolumeBootSector->BootSectorMagic);
244 return FALSE;
245 }
246
247 //
248 // Check the FAT cluster size
249 // We do not support clusters bigger than 64k
250 //
251 if ((ISFATX(Volume->FatType) && 64 * 1024 < FatXVolumeBootSector->SectorsPerCluster * 512) ||
252 (! ISFATX(Volume->FatType) && 64 * 1024 < FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector))
253 {
254 FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this.");
255 return FALSE;
256 }
257
258 //
259 // Get the sectors per FAT,
260 // root directory starting sector,
261 // and data sector start
262 //
263 if (ISFATX(Volume->FatType))
264 {
265 Volume->BytesPerSector = 512;
266 Volume->SectorsPerCluster = SWAPD(FatXVolumeBootSector->SectorsPerCluster);
267 Volume->FatSectorStart = (0x1000 / Volume->BytesPerSector);
268 Volume->ActiveFatSectorStart = Volume->FatSectorStart;
269 Volume->NumberOfFats = 1;
270 FatSize = (ULONG)(PartitionSectorCount / Volume->SectorsPerCluster *
271 (Volume->FatType == FATX16 ? 2 : 4));
272 Volume->SectorsPerFat = ROUND_UP(FatSize, 0x1000) / Volume->BytesPerSector;
273
274 Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
275 Volume->RootDirSectors = FatXVolumeBootSector->SectorsPerCluster;
276
277 Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
278 }
279 else if (Volume->FatType != FAT32)
280 {
281 Volume->BytesPerSector = FatVolumeBootSector->BytesPerSector;
282 Volume->SectorsPerCluster = FatVolumeBootSector->SectorsPerCluster;
283 Volume->FatSectorStart = FatVolumeBootSector->ReservedSectors;
284 Volume->ActiveFatSectorStart = Volume->FatSectorStart;
285 Volume->NumberOfFats = FatVolumeBootSector->NumberOfFats;
286 Volume->SectorsPerFat = FatVolumeBootSector->SectorsPerFat;
287
288 Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
289 Volume->RootDirSectors = ((FatVolumeBootSector->RootDirEntries * 32) + (Volume->BytesPerSector - 1)) / Volume->BytesPerSector;
290
291 Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
292 }
293 else
294 {
295 Volume->BytesPerSector = Fat32VolumeBootSector->BytesPerSector;
296 Volume->SectorsPerCluster = Fat32VolumeBootSector->SectorsPerCluster;
297 Volume->FatSectorStart = Fat32VolumeBootSector->ReservedSectors;
298 Volume->ActiveFatSectorStart = Volume->FatSectorStart +
299 ((Fat32VolumeBootSector->ExtendedFlags & 0x80) ? ((Fat32VolumeBootSector->ExtendedFlags & 0x0f) * Fat32VolumeBootSector->SectorsPerFatBig) : 0);
300 Volume->NumberOfFats = Fat32VolumeBootSector->NumberOfFats;
301 Volume->SectorsPerFat = Fat32VolumeBootSector->SectorsPerFatBig;
302
303 Volume->RootDirStartCluster = Fat32VolumeBootSector->RootDirStartCluster;
304 Volume->DataSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
305
306 //
307 // Check version
308 // we only work with version 0
309 //
310 if (Fat32VolumeBootSector->FileSystemVersion != 0)
311 {
312 FileSystemError("FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
313 return FALSE;
314 }
315 }
316
317 Volume->FatCacheSize = min(Volume->SectorsPerFat, FAT_MAX_CACHE_SIZE / Volume->BytesPerSector);
318 TRACE("FAT cache is %d sectors, %d bytes\n", Volume->FatCacheSize, Volume->FatCacheSize * Volume->BytesPerSector);
319
320 Volume->FatCache = FrLdrTempAlloc(Volume->FatCacheSize * Volume->BytesPerSector, TAG_FAT_CACHE);
321 if (!Volume->FatCache)
322 {
323 FileSystemError("Cannot allocate memory for FAT cache");
324 return FALSE;
325 }
326
327 Volume->FatCacheIndex = FrLdrTempAlloc(Volume->FatCacheSize * sizeof(*Volume->FatCacheIndex), TAG_FAT_VOLUME);
328 if (!Volume->FatCacheIndex)
329 {
330 FileSystemError("Cannot allocate memory for FAT cache index");
332 return FALSE;
333 }
334
335 // read the beginning of the FAT (or the whole one) to cache
336 if (!FatReadVolumeSectors(Volume, Volume->ActiveFatSectorStart, Volume->FatCacheSize, Volume->FatCache))
337 {
338 FileSystemError("Error when reading FAT cache");
340 FrLdrTempFree(Volume->FatCacheIndex, TAG_FAT_VOLUME);
341 return FALSE;
342 }
343
344 // fill the index with sector numbers
345 for (i = 0; i < Volume->FatCacheSize; i++)
346 {
347 Volume->FatCacheIndex[i] = Volume->ActiveFatSectorStart + i;
348 }
349
350 return TRUE;
351}
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:471
VOID FatSwapFatBootSector(PFAT_BOOTSECTOR Obj)
Definition: fat.c:60
VOID FatSwapFat32BootSector(PFAT32_BOOTSECTOR Obj)
Definition: fat.c:75
#define TAG_FAT_CACHE
Definition: fat.c:35
VOID FatSwapFatXBootSector(PFATX_BOOTSECTOR Obj)
Definition: fat.c:95
ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONGLONG PartitionSectorCount)
Definition: fat.c:353
#define FAT_MAX_CACHE_SIZE
Definition: fat.c:37
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static int ErrMsg(int Error)
Definition: shlextdbg.cpp:71
USHORT BootSectorMagic
Definition: fsutil.c:98
CHAR FileSystemType[8]
Definition: fsutil.c:94
UCHAR Reserved[12]
Definition: fsutil.c:88
UCHAR MediaDescriptor
Definition: fsutil.c:76
ULONG HiddenSectors
Definition: fsutil.c:80
UCHAR NumberOfFats
Definition: fsutil.c:73
ULONG VolumeSerialNumber
Definition: fsutil.c:92
CHAR VolumeLabel[11]
Definition: fsutil.c:93
USHORT ExtendedFlags
Definition: fsutil.c:83
ULONG SectorsPerFatBig
Definition: fsutil.c:82
UCHAR JumpBoot[3]
Definition: fsutil.c:68
CHAR OemName[8]
Definition: fsutil.c:69
USHORT NumberOfHeads
Definition: fsutil.c:79
USHORT ReservedSectors
Definition: fsutil.c:72
USHORT RootDirEntries
Definition: fsutil.c:74
USHORT FsInfo
Definition: fsutil.c:86
USHORT BytesPerSector
Definition: fsutil.c:70
USHORT FileSystemVersion
Definition: fsutil.c:84
ULONG TotalSectorsBig
Definition: fsutil.c:81
UCHAR BootSignature
Definition: fsutil.c:91
ULONG RootDirStartCluster
Definition: fsutil.c:85
UCHAR DriveNumber
Definition: fsutil.c:89
UCHAR SectorsPerCluster
Definition: fsutil.c:71
USHORT SectorsPerFat
Definition: fsutil.c:77
USHORT SectorsPerTrack
Definition: fsutil.c:78
UCHAR Reserved1
Definition: fsutil.c:90
USHORT BackupBootSector
Definition: fsutil.c:87
USHORT TotalSectors
Definition: fsutil.c:75
ULONG VolumeSerialNumber
Definition: fat.h:91
ULONG Unknown
Definition: fat.h:94
USHORT NumberOfFats
Definition: fat.h:93
ULONG TotalSectorsBig
Definition: fsutil.c:51
UCHAR JumpBoot[3]
Definition: fsutil.c:38
USHORT SectorsPerTrack
Definition: fsutil.c:48
CHAR VolumeLabel[11]
Definition: fsutil.c:56
USHORT NumberOfHeads
Definition: fsutil.c:49
CHAR OemName[8]
Definition: fsutil.c:39
ULONG HiddenSectors
Definition: fsutil.c:50
CHAR FileSystemType[8]
Definition: fsutil.c:57
ULONG VolumeSerialNumber
Definition: fsutil.c:55
UCHAR MediaDescriptor
Definition: fsutil.c:46
USHORT BootSectorMagic
Definition: fsutil.c:61
UCHAR Reserved1
Definition: fsutil.c:53
UCHAR DriveNumber
Definition: fsutil.c:52
UCHAR BootSignature
Definition: fsutil.c:54

Referenced by FatMount().

◆ FatParseShortFileName()

void FatParseShortFileName ( PCHAR  Buffer,
PDIRENTRY  DirEntry 
)

Definition at line 869 of file fat.c.

870{
871 ULONG Idx;
872
873 Idx = 0;
875
876 //
877 // Fixup first character
878 //
879 if (DirEntry->FileName[0] == 0x05)
880 {
881 DirEntry->FileName[0] = 0xE5;
882 }
883
884 //
885 // Get the file name
886 //
887 while (Idx < 8)
888 {
889 if (DirEntry->FileName[Idx] == ' ')
890 {
891 break;
892 }
893
894 Buffer[Idx] = DirEntry->FileName[Idx];
895 Idx++;
896 }
897
898 //
899 // Get extension
900 //
901 if ((DirEntry->FileName[8] != ' '))
902 {
903 Buffer[Idx++] = '.';
904 Buffer[Idx++] = (DirEntry->FileName[8] == ' ') ? '\0' : DirEntry->FileName[8];
905 Buffer[Idx++] = (DirEntry->FileName[9] == ' ') ? '\0' : DirEntry->FileName[9];
906 Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10];
907 }
908
909 //TRACE("FatParseShortFileName() ShortName = %s\n", Buffer);
910}

Referenced by FatSearchDirectoryBufferForFile().

◆ FatRead()

ARC_STATUS FatRead ( ULONG  FileId,
VOID Buffer,
ULONG  N,
ULONG Count 
)

Definition at line 1462 of file fat.c.

1463{
1466
1467 //
1468 // Call old read method
1469 //
1471
1472 //
1473 // Check for success
1474 //
1475 if (Success)
1476 return ESUCCESS;
1477 else
1478 return EIO;
1479}
#define N
Definition: crc32.c:57
#define EIO
Definition: acclib.h:81
static BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG *BytesRead, PVOID Buffer)
Definition: fat.c:1199
@ Success
Definition: eventcreate.c:712

◆ FatReadAdjacentClusters()

static BOOLEAN FatReadAdjacentClusters ( PFAT_VOLUME_INFO  Volume,
UINT32  StartClusterNumber,
UINT32  MaxClusters,
PVOID  Buffer,
PUINT32  ClustersRead,
PUINT32  LastClusterNumber 
)
static

Definition at line 1080 of file fat.c.

1087{
1088 UINT32 NextClusterNumber;
1089 UINT32 ClustersToRead = 1;
1090 UINT32 PrevClusterNumber = StartClusterNumber;
1091 UINT32 ClusterStartSector = ((PrevClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
1092
1093 *ClustersRead = 0;
1094 *LastClusterNumber = 0;
1095
1096 if (!FatGetFatEntry(Volume, StartClusterNumber, &NextClusterNumber))
1097 {
1098 return FALSE;
1099 }
1100
1101 // getting the number of adjacent clusters
1102 while (!FAT_IS_END_CLUSTER(NextClusterNumber) && ClustersToRead < MaxClusters && (NextClusterNumber == PrevClusterNumber + 1))
1103 {
1104 ClustersToRead++;
1105 PrevClusterNumber = NextClusterNumber;
1106 if (!FatGetFatEntry(Volume, PrevClusterNumber, &NextClusterNumber))
1107 {
1108 return FALSE;
1109 }
1110 }
1111
1112 if (!FatReadVolumeSectors(Volume, ClusterStartSector, ClustersToRead * Volume->SectorsPerCluster, Buffer))
1113 {
1114 return FALSE;
1115 }
1116
1117 *ClustersRead = ClustersToRead;
1118 *LastClusterNumber = NextClusterNumber;
1119
1120 return !FAT_IS_END_CLUSTER(NextClusterNumber) && ClustersToRead < MaxClusters;
1121}

Referenced by FatReadClusterChain().

◆ FatReadClusterChain()

static BOOLEAN FatReadClusterChain ( PFAT_VOLUME_INFO  Volume,
UINT32  StartClusterNumber,
UINT32  NumberOfClusters,
PVOID  Buffer,
PUINT32  LastClusterNumber 
)
static

Definition at line 1128 of file fat.c.

1129{
1130 UINT32 ClustersRead, NextClusterNumber, ClustersLeft = NumberOfClusters;
1131
1132 TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
1133
1134 ASSERT(NumberOfClusters > 0);
1135
1136 while (FatReadAdjacentClusters(Volume, StartClusterNumber, ClustersLeft, Buffer, &ClustersRead, &NextClusterNumber))
1137 {
1138 ClustersLeft -= ClustersRead;
1139 Buffer = (PVOID)((ULONG_PTR)Buffer + (ClustersRead * Volume->SectorsPerCluster * Volume->BytesPerSector));
1140 StartClusterNumber = NextClusterNumber;
1141 }
1142
1143 if (LastClusterNumber)
1144 {
1145 *LastClusterNumber = NextClusterNumber;
1146 }
1147
1148 return (ClustersRead > 0);
1149}
static BOOLEAN FatReadAdjacentClusters(PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32 MaxClusters, PVOID Buffer, PUINT32 ClustersRead, PUINT32 LastClusterNumber)
Definition: fat.c:1080
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by FatBufferDirectory(), and FatReadFile().

◆ FatReadFile()

static BOOLEAN FatReadFile ( PFAT_FILE_INFO  FatFileInfo,
ULONG  BytesToRead,
ULONG BytesRead,
PVOID  Buffer 
)
static

Definition at line 1199 of file fat.c.

1200{
1201 PFAT_VOLUME_INFO Volume = FatFileInfo->Volume;
1202 UINT32 NextClusterNumber, BytesPerCluster;
1203
1204 TRACE("FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer);
1205
1206 if (BytesRead != NULL)
1207 {
1208 *BytesRead = 0;
1209 }
1210
1211 //
1212 // If the user is trying to read past the end of
1213 // the file then return success with BytesRead == 0.
1214 //
1215 if (FatFileInfo->FilePointer >= FatFileInfo->FileSize)
1216 {
1217 return TRUE;
1218 }
1219
1220 //
1221 // If the user is trying to read more than there is to read
1222 // then adjust the amount to read.
1223 //
1224 if ((FatFileInfo->FilePointer + BytesToRead) > FatFileInfo->FileSize)
1225 {
1226 BytesToRead = (FatFileInfo->FileSize - FatFileInfo->FilePointer);
1227 }
1228
1229 //
1230 // Ok, now we have to perform at most 3 calculations
1231 // I'll draw you a picture (using nifty ASCII art):
1232 //
1233 // CurrentFilePointer -+
1234 // |
1235 // +----------------+
1236 // |
1237 // +-----------+-----------+-----------+-----------+
1238 // | Cluster 1 | Cluster 2 | Cluster 3 | Cluster 4 |
1239 // +-----------+-----------+-----------+-----------+
1240 // | |
1241 // +---------------+--------------------+
1242 // |
1243 // BytesToRead -------+
1244 //
1245 // 1 - The first calculation (and read) will align
1246 // the file pointer with the next cluster.
1247 // boundary (if we are supposed to read that much)
1248 // 2 - The next calculation (and read) will read
1249 // in all the full clusters that the requested
1250 // amount of data would cover (in this case
1251 // clusters 2 & 3).
1252 // 3 - The last calculation (and read) would read
1253 // in the remainder of the data requested out of
1254 // the last cluster.
1255 //
1256
1257 BytesPerCluster = Volume->SectorsPerCluster * Volume->BytesPerSector;
1258
1259 //
1260 // Only do the first read if we
1261 // aren't aligned on a cluster boundary
1262 //
1263 if (FatFileInfo->FilePointer % BytesPerCluster)
1264 {
1265 //
1266 // Do the math for our first read
1267 //
1268 UINT32 OffsetInCluster = FatFileInfo->FilePointer % BytesPerCluster;
1269 UINT32 LengthInCluster = min(BytesToRead, BytesPerCluster - OffsetInCluster);
1270
1271 ASSERT(LengthInCluster <= BytesPerCluster && LengthInCluster > 0);
1272
1273 //
1274 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
1275 //
1276 if (!FatReadPartialCluster(Volume, FatFileInfo->CurrentCluster, OffsetInCluster, LengthInCluster, Buffer))
1277 {
1278 return FALSE;
1279 }
1280 if (BytesRead != NULL)
1281 {
1282 *BytesRead += LengthInCluster;
1283 }
1284 BytesToRead -= LengthInCluster;
1285 FatFileInfo->FilePointer += LengthInCluster;
1286 Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInCluster);
1287
1288 // get the next cluster if needed
1289 if ((LengthInCluster + OffsetInCluster) == BytesPerCluster)
1290 {
1291 if (!FatGetFatEntry(Volume, FatFileInfo->CurrentCluster, &NextClusterNumber))
1292 {
1293 return FALSE;
1294 }
1295
1296 FatFileInfo->CurrentCluster = NextClusterNumber;
1297 TRACE("FatReadFile() FatFileInfo->CurrentCluster = 0x%x\n", FatFileInfo->CurrentCluster);
1298 }
1299 }
1300
1301 //
1302 // Do the math for our second read (if any data left)
1303 //
1304 if (BytesToRead > 0)
1305 {
1306 //
1307 // Determine how many full clusters we need to read
1308 //
1309 UINT32 NumberOfClusters = BytesToRead / BytesPerCluster;
1310
1311 TRACE("Going to read: %u clusters\n", NumberOfClusters);
1312
1313 if (NumberOfClusters > 0)
1314 {
1315 UINT32 BytesReadHere = NumberOfClusters * BytesPerCluster;
1316
1318
1319 if (!FatReadClusterChain(Volume, FatFileInfo->CurrentCluster, NumberOfClusters, Buffer, &NextClusterNumber))
1320 {
1321 return FALSE;
1322 }
1323
1324 if (BytesRead != NULL)
1325 {
1326 *BytesRead += BytesReadHere;
1327 }
1328 BytesToRead -= BytesReadHere;
1329 Buffer = (PVOID)((ULONG_PTR)Buffer + BytesReadHere);
1330
1331 ASSERT(!FAT_IS_END_CLUSTER(NextClusterNumber) || BytesToRead == 0);
1332
1333 FatFileInfo->FilePointer += BytesReadHere;
1334 FatFileInfo->CurrentCluster = NextClusterNumber;
1335 TRACE("FatReadFile() FatFileInfo->CurrentCluster = 0x%x\n", FatFileInfo->CurrentCluster);
1336 }
1337 }
1338
1339 //
1340 // Do the math for our third read (if any data left)
1341 //
1342 if (BytesToRead > 0)
1343 {
1345
1346 //
1347 // Now do the read and update BytesRead & FilePointer
1348 //
1349 if (!FatReadPartialCluster(Volume, FatFileInfo->CurrentCluster, 0, BytesToRead, Buffer))
1350 {
1351 return FALSE;
1352 }
1353 if (BytesRead != NULL)
1354 {
1355 *BytesRead += BytesToRead;
1356 }
1357 FatFileInfo->FilePointer += BytesToRead;
1358 }
1359
1360 return TRUE;
1361}
BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
Definition: fat.c:1155
ULONG CurrentCluster
Definition: fat.h:153
ULONG FileSize
Definition: fat.h:151
PFAT_VOLUME_INFO Volume
Definition: fat.h:150
ULONG FilePointer
Definition: fat.h:152
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870

Referenced by FatRead().

◆ FatReadPartialCluster()

BOOLEAN FatReadPartialCluster ( PFAT_VOLUME_INFO  Volume,
ULONG  ClusterNumber,
ULONG  StartingOffset,
ULONG  Length,
PVOID  Buffer 
)

Definition at line 1155 of file fat.c.

1156{
1157 ULONG ClusterStartSector;
1158 ULONG SectorOffset, ReadSize, SectorCount;
1161
1162 //TRACE("FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer);
1163
1164 ClusterStartSector = ((ClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
1165
1166 // This is the offset of the data in sectors
1167 SectorOffset = (StartingOffset / Volume->BytesPerSector);
1168 StartingOffset %= Volume->BytesPerSector;
1169
1170 // Calculate how many sectors we need to read
1171 SectorCount = (StartingOffset + Length + Volume->BytesPerSector - 1) / Volume->BytesPerSector;
1172
1173 // Calculate rounded up read size
1174 ReadSize = SectorCount * Volume->BytesPerSector;
1175
1177 if (!ReadBuffer)
1178 {
1179 return FALSE;
1180 }
1181
1182 if (FatReadVolumeSectors(Volume, ClusterStartSector + SectorOffset, SectorCount, ReadBuffer))
1183 {
1185 Success = TRUE;
1186 }
1187
1189
1190 return Success;
1191}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#define SectorOffset(L)
Definition: cdprocs.h:1622
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102

Referenced by FatReadFile().

◆ FatReadVolumeSectors()

BOOLEAN FatReadVolumeSectors ( PFAT_VOLUME_INFO  Volume,
ULONG  SectorNumber,
ULONG  SectorCount,
PVOID  Buffer 
)

Definition at line 1363 of file fat.c.

1364{
1366 ULONG Count;
1368
1369 //TRACE("FatReadVolumeSectors(): SectorNumber %d, SectorCount %d, Buffer %p\n",
1370 // SectorNumber, SectorCount, Buffer);
1371
1372 //
1373 // Seek to right position
1374 //
1375 Position.QuadPart = (ULONGLONG)SectorNumber * Volume->BytesPerSector;
1376 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
1377 if (Status != ESUCCESS)
1378 {
1379 TRACE("FatReadVolumeSectors() Failed to seek\n");
1380 return FALSE;
1381 }
1382
1383 //
1384 // Read data
1385 //
1386 Status = ArcRead(Volume->DeviceId, Buffer, SectorCount * Volume->BytesPerSector, &Count);
1387 if (Status != ESUCCESS || Count != SectorCount * Volume->BytesPerSector)
1388 {
1389 TRACE("FatReadVolumeSectors() Failed to read\n");
1390 return FALSE;
1391 }
1392
1393 // Return success
1394 return TRUE;
1395}
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by FatBufferDirectory(), FatGetFatSector(), FatOpenVolume(), FatReadAdjacentClusters(), and FatReadPartialCluster().

◆ FatSearchDirectoryBufferForFile()

BOOLEAN FatSearchDirectoryBufferForFile ( PFAT_VOLUME_INFO  Volume,
PVOID  DirectoryBuffer,
ULONG  EntryCount,
PCHAR  FileName,
PFAT_FILE_INFO  FatFileInfoPointer 
)

Definition at line 506 of file fat.c.

507{
508 ULONG EntryCount;
509 ULONG CurrentEntry;
510 CHAR LfnNameBuffer[265];
511 CHAR ShortNameBuffer[20];
512 ULONG StartCluster;
513 DIRENTRY OurDirEntry;
514 LFN_DIRENTRY OurLfnDirEntry;
515 PDIRENTRY DirEntry = &OurDirEntry;
516 PLFN_DIRENTRY LfnDirEntry = &OurLfnDirEntry;
517
518 EntryCount = DirectorySize / sizeof(DIRENTRY);
519
520 TRACE("FatSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName);
521
522 RtlZeroMemory(ShortNameBuffer, 13 * sizeof(CHAR));
523 RtlZeroMemory(LfnNameBuffer, 261 * sizeof(CHAR));
524
525 for (CurrentEntry=0; CurrentEntry<EntryCount; CurrentEntry++, DirectoryBuffer = ((PDIRENTRY)DirectoryBuffer)+1)
526 {
527 OurLfnDirEntry = *((PLFN_DIRENTRY) DirectoryBuffer);
528 FatSwapLFNDirEntry(LfnDirEntry);
529 OurDirEntry = *((PDIRENTRY) DirectoryBuffer);
531
532 //TRACE("Dumping directory entry %d:\n", CurrentEntry);
533 //DbgDumpBuffer(DPRINT_FILESYSTEM, DirEntry, sizeof(DIRENTRY));
534
535 //
536 // Check if this is the last file in the directory
537 // If DirEntry[0] == 0x00 then that means all the
538 // entries after this one are unused. If this is the
539 // last entry then we didn't find the file in this directory.
540 //
541 if (DirEntry->FileName[0] == '\0')
542 {
543 return FALSE;
544 }
545
546 //
547 // Check if this is a deleted entry or not
548 //
549 if (DirEntry->FileName[0] == '\xE5')
550 {
551 RtlZeroMemory(ShortNameBuffer, 13 * sizeof(CHAR));
552 RtlZeroMemory(LfnNameBuffer, 261 * sizeof(CHAR));
553 continue;
554 }
555
556 //
557 // Check if this is a LFN entry
558 // If so it needs special handling
559 //
560 if (DirEntry->Attr == ATTR_LONG_NAME)
561 {
562 //
563 // Check to see if this is a deleted LFN entry, if so continue
564 //
565 if (LfnDirEntry->SequenceNumber & 0x80)
566 {
567 continue;
568 }
569
570 //
571 // Mask off high two bits of sequence number
572 // and make the sequence number zero-based
573 //
574 LfnDirEntry->SequenceNumber &= 0x3F;
575 LfnDirEntry->SequenceNumber--;
576
577 //
578 // Get all 13 LFN entry characters
579 //
580 if (LfnDirEntry->Name0_4[0] != 0xFFFF)
581 {
582 LfnNameBuffer[0 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[0];
583 }
584 if (LfnDirEntry->Name0_4[1] != 0xFFFF)
585 {
586 LfnNameBuffer[1 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[1];
587 }
588 if (LfnDirEntry->Name0_4[2] != 0xFFFF)
589 {
590 LfnNameBuffer[2 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[2];
591 }
592 if (LfnDirEntry->Name0_4[3] != 0xFFFF)
593 {
594 LfnNameBuffer[3 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[3];
595 }
596 if (LfnDirEntry->Name0_4[4] != 0xFFFF)
597 {
598 LfnNameBuffer[4 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[4];
599 }
600 if (LfnDirEntry->Name5_10[0] != 0xFFFF)
601 {
602 LfnNameBuffer[5 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[0];
603 }
604 if (LfnDirEntry->Name5_10[1] != 0xFFFF)
605 {
606 LfnNameBuffer[6 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[1];
607 }
608 if (LfnDirEntry->Name5_10[2] != 0xFFFF)
609 {
610 LfnNameBuffer[7 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[2];
611 }
612 if (LfnDirEntry->Name5_10[3] != 0xFFFF)
613 {
614 LfnNameBuffer[8 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[3];
615 }
616 if (LfnDirEntry->Name5_10[4] != 0xFFFF)
617 {
618 LfnNameBuffer[9 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[4];
619 }
620 if (LfnDirEntry->Name5_10[5] != 0xFFFF)
621 {
622 LfnNameBuffer[10 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[5];
623 }
624 if (LfnDirEntry->Name11_12[0] != 0xFFFF)
625 {
626 LfnNameBuffer[11 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[0];
627 }
628 if (LfnDirEntry->Name11_12[1] != 0xFFFF)
629 {
630 LfnNameBuffer[12 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[1];
631 }
632
633 //TRACE("Dumping long name buffer:\n");
634 //DbgDumpBuffer(DPRINT_FILESYSTEM, LfnNameBuffer, 260);
635
636 continue;
637 }
638
639 //
640 // Check for the volume label attribute
641 // and skip over this entry if found
642 //
643 if (DirEntry->Attr & ATTR_VOLUMENAME)
644 {
645 RtlZeroMemory(ShortNameBuffer, 13 * sizeof(UCHAR));
646 RtlZeroMemory(LfnNameBuffer, 261 * sizeof(UCHAR));
647 continue;
648 }
649
650 //
651 // If we get here then we've found a short file name
652 // entry and LfnNameBuffer contains the long file
653 // name or zeroes. All we have to do now is see if the
654 // file name matches either the short or long file name
655 // and fill in the FAT_FILE_INFO structure if it does
656 // or zero our buffers and continue looking.
657 //
658
659 //
660 // Get short file name
661 //
662 FatParseShortFileName(ShortNameBuffer, DirEntry);
663
664 //TRACE("Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer);
665 //TRACE("Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer);
666
667 //
668 // See if the file name matches either the short or long name
669 //
670 if (((strlen(FileName) == strlen(LfnNameBuffer)) && (_stricmp(FileName, LfnNameBuffer) == 0)) ||
671 ((strlen(FileName) == strlen(ShortNameBuffer)) && (_stricmp(FileName, ShortNameBuffer) == 0)))
672 {
673 //
674 // We found the entry, now fill in the FAT_FILE_INFO struct
675 //
676 FatFileInfoPointer->Attributes = DirEntry->Attr;
677 FatFileInfoPointer->FileSize = DirEntry->Size;
678 FatFileInfoPointer->FilePointer = 0;
679 StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
680 FatFileInfoPointer->CurrentCluster = StartCluster;
681 FatFileInfoPointer->StartCluster = StartCluster;
682
683 TRACE("MSDOS Directory Entry:\n");
684 TRACE("FileName[11] = %c%c%c%c%c%c%c%c%c%c%c\n", DirEntry->FileName[0], DirEntry->FileName[1], DirEntry->FileName[2], DirEntry->FileName[3], DirEntry->FileName[4], DirEntry->FileName[5], DirEntry->FileName[6], DirEntry->FileName[7], DirEntry->FileName[8], DirEntry->FileName[9], DirEntry->FileName[10]);
685 TRACE("Attr = 0x%x\n", DirEntry->Attr);
686 TRACE("ReservedNT = 0x%x\n", DirEntry->ReservedNT);
687 TRACE("TimeInTenths = %d\n", DirEntry->TimeInTenths);
688 TRACE("CreateTime = %d\n", DirEntry->CreateTime);
689 TRACE("CreateDate = %d\n", DirEntry->CreateDate);
690 TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
691 TRACE("ClusterHigh = 0x%x\n", DirEntry->ClusterHigh);
692 TRACE("Time = %d\n", DirEntry->Time);
693 TRACE("Date = %d\n", DirEntry->Date);
694 TRACE("ClusterLow = 0x%x\n", DirEntry->ClusterLow);
695 TRACE("Size = %d\n", DirEntry->Size);
696 TRACE("StartCluster = 0x%x\n", StartCluster);
697
698 return TRUE;
699 }
700
701 //
702 // Nope, no match - zero buffers and continue looking
703 //
704 RtlZeroMemory(ShortNameBuffer, 13 * sizeof(UCHAR));
705 RtlZeroMemory(LfnNameBuffer, 261 * sizeof(UCHAR));
706 }
707
708 return FALSE;
709}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ATTR_VOLUMENAME
Definition: fat.h:162
#define ATTR_LONG_NAME
Definition: fat.h:165
struct DIRENTRY * PDIRENTRY
struct LFN_DIRENTRY * PLFN_DIRENTRY
VOID FatSwapDirEntry(PDIRENTRY Obj)
Definition: fat.c:102
VOID FatSwapLFNDirEntry(PLFN_DIRENTRY Obj)
Definition: fat.c:114
void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry)
Definition: fat.c:869
#define _stricmp
Definition: cat.c:22
Definition: fat.h:103
WCHAR Name11_12[2]
Definition: fat.h:127
UCHAR SequenceNumber
Definition: fat.h:120
WCHAR Name5_10[6]
Definition: fat.h:125
WCHAR Name0_4[5]
Definition: fat.h:121

Referenced by FatLookupFile().

◆ FatSeek()

ARC_STATUS FatSeek ( ULONG  FileId,
LARGE_INTEGER Position,
SEEKMODE  SeekMode 
)

Definition at line 1481 of file fat.c.

1482{
1485 LARGE_INTEGER NewPosition = *Position;
1486
1487 switch (SeekMode)
1488 {
1489 case SeekAbsolute:
1490 break;
1491 case SeekRelative:
1492 NewPosition.QuadPart += (ULONGLONG)FileHandle->FilePointer;
1493 break;
1494 default:
1495 ASSERT(FALSE);
1496 return EINVAL;
1497 }
1498
1499 if (NewPosition.HighPart != 0)
1500 return EINVAL;
1501 if (NewPosition.LowPart >= FileHandle->FileSize)
1502 return EINVAL;
1503
1504 TRACE("FatSeek() NewPosition = %u, OldPointer = %u, SeekMode = %d\n", NewPosition.LowPart, FileHandle->FilePointer, SeekMode);
1505
1506 {
1507 UINT32 OldClusterIdx = FileHandle->FilePointer / (Volume->SectorsPerCluster * Volume->BytesPerSector);
1508 UINT32 NewClusterIdx = NewPosition.LowPart / (Volume->SectorsPerCluster * Volume->BytesPerSector);
1509
1510 TRACE("FatSeek() OldClusterIdx: %u, NewClusterIdx: %u\n", OldClusterIdx, NewClusterIdx);
1511
1512 if (NewClusterIdx != OldClusterIdx)
1513 {
1514 UINT32 CurrentClusterIdx, ClusterNumber;
1515
1516 if (NewClusterIdx > OldClusterIdx)
1517 {
1518 CurrentClusterIdx = OldClusterIdx;
1519 ClusterNumber = FileHandle->CurrentCluster;
1520 }
1521 else
1522 {
1523 CurrentClusterIdx = 0;
1524 ClusterNumber = FileHandle->StartCluster;
1525 }
1526
1527 for (; CurrentClusterIdx < NewClusterIdx; CurrentClusterIdx++)
1528 {
1529 if (!FatGetFatEntry(Volume, ClusterNumber, &ClusterNumber))
1530 {
1531 return EIO;
1532 }
1533 }
1534 FileHandle->CurrentCluster = ClusterNumber;
1535 }
1536 }
1537
1538 FileHandle->FilePointer = NewPosition.LowPart;
1539
1540 return ESUCCESS;
1541}
#define EINVAL
Definition: acclib.h:90
@ SeekRelative
Definition: arc.h:60
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106

◆ FatSwapDirEntry()

VOID FatSwapDirEntry ( PDIRENTRY  Obj)

Definition at line 102 of file fat.c.

103{
104 SW(Obj, CreateTime);
105 SW(Obj, CreateDate);
106 SW(Obj, LastAccessDate);
107 SW(Obj, ClusterHigh);
108 SW(Obj, Time);
109 SW(Obj, Date);
110 SW(Obj, ClusterLow);
111 SD(Obj, Size);
112}
#define SW(Object, Field)
Definition: bytesex.h:11
#define SD(Object, Field)
Definition: bytesex.h:10
static PLARGE_INTEGER Time
Definition: time.c:105
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by FatSearchDirectoryBufferForFile().

◆ FatSwapFat32BootSector()

VOID FatSwapFat32BootSector ( PFAT32_BOOTSECTOR  Obj)

Definition at line 75 of file fat.c.

76{
77 SW(Obj, BytesPerSector);
78 SW(Obj, ReservedSectors);
79 SW(Obj, RootDirEntries);
80 SW(Obj, TotalSectors);
81 SW(Obj, SectorsPerFat);
83 SD(Obj, HiddenSectors);
84 SD(Obj, TotalSectorsBig);
85 SD(Obj, SectorsPerFatBig);
86 SW(Obj, ExtendedFlags);
87 SW(Obj, FileSystemVersion);
88 SD(Obj, RootDirStartCluster);
89 SW(Obj, FsInfo);
91 SD(Obj, VolumeSerialNumber);
92 SW(Obj, BootSectorMagic);
93}
BOOL BackupBootSector(LPCTSTR lpszVolumeName)
Definition: install.c:61
_In_ ULONG _In_ ULONG _In_ ULONG NumberOfHeads
Definition: iofuncs.h:2072

Referenced by FatOpenVolume().

◆ FatSwapFatBootSector()

VOID FatSwapFatBootSector ( PFAT_BOOTSECTOR  Obj)

Definition at line 60 of file fat.c.

61{
62 SW(Obj, BytesPerSector);
63 SW(Obj, ReservedSectors);
64 SW(Obj, RootDirEntries);
65 SW(Obj, TotalSectors);
66 SW(Obj, SectorsPerFat);
69 SD(Obj, HiddenSectors);
70 SD(Obj, TotalSectorsBig);
71 SD(Obj, VolumeSerialNumber);
72 SW(Obj, BootSectorMagic);
73}
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2071

Referenced by FatOpenVolume().

◆ FatSwapFatXBootSector()

VOID FatSwapFatXBootSector ( PFATX_BOOTSECTOR  Obj)

Definition at line 95 of file fat.c.

96{
97 SD(Obj, VolumeSerialNumber);
98 SD(Obj, SectorsPerCluster);
99 SW(Obj, NumberOfFats);
100}

Referenced by FatOpenVolume().

◆ FatSwapFatXDirEntry()

VOID FatSwapFatXDirEntry ( PFATX_DIRENTRY  Obj)

Definition at line 126 of file fat.c.

127{
128 SD(Obj, StartCluster);
129 SD(Obj, Size);
130 SW(Obj, Time);
131 SW(Obj, Date);
132 SW(Obj, CreateTime);
133 SW(Obj, CreateDate);
134 SW(Obj, LastAccessTime);
135 SW(Obj, LastAccessDate);
136}

Referenced by FatXSearchDirectoryBufferForFile().

◆ FatSwapLFNDirEntry()

VOID FatSwapLFNDirEntry ( PLFN_DIRENTRY  Obj)

Definition at line 114 of file fat.c.

115{
116 int i;
117 SW(Obj, StartCluster);
118 for(i = 0; i < 5; i++)
119 Obj->Name0_4[i] = SWAPW(Obj->Name0_4[i]);
120 for(i = 0; i < 6; i++)
121 Obj->Name5_10[i] = SWAPW(Obj->Name5_10[i]);
122 for(i = 0; i < 2; i++)
123 Obj->Name11_12[i] = SWAPW(Obj->Name11_12[i]);
124}

Referenced by FatSearchDirectoryBufferForFile().

◆ FatXSearchDirectoryBufferForFile()

static BOOLEAN FatXSearchDirectoryBufferForFile ( PFAT_VOLUME_INFO  Volume,
PVOID  DirectoryBuffer,
ULONG  DirectorySize,
PCHAR  FileName,
PFAT_FILE_INFO  FatFileInfoPointer 
)
static

Definition at line 711 of file fat.c.

712{
713 ULONG EntryCount;
714 ULONG CurrentEntry;
716 FATX_DIRENTRY OurDirEntry;
717 PFATX_DIRENTRY DirEntry = &OurDirEntry;
718
719 EntryCount = DirectorySize / sizeof(FATX_DIRENTRY);
720
721 TRACE("FatXSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName);
722
724
725 for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++, DirectoryBuffer = ((PFATX_DIRENTRY)DirectoryBuffer)+1)
726 {
727 OurDirEntry = *(PFATX_DIRENTRY) DirectoryBuffer;
728 FatSwapFatXDirEntry(&OurDirEntry);
729 if (0xff == DirEntry->FileNameSize)
730 {
731 break;
732 }
733 if (0xe5 == DirEntry->FileNameSize)
734 {
735 continue;
736 }
737 if (FileNameLen == DirEntry->FileNameSize &&
738 0 == _strnicmp(FileName, DirEntry->FileName, FileNameLen))
739 {
740 /*
741 * We found the entry, now fill in the FAT_FILE_INFO struct
742 */
743 FatFileInfoPointer->Attributes = DirEntry->Attr;
744 FatFileInfoPointer->FileSize = DirEntry->Size;
745 FatFileInfoPointer->FilePointer = 0;
746 FatFileInfoPointer->CurrentCluster = DirEntry->StartCluster;
747 FatFileInfoPointer->StartCluster = DirEntry->StartCluster;
748
749 TRACE("FATX Directory Entry:\n");
750 TRACE("FileNameSize = %d\n", DirEntry->FileNameSize);
751 TRACE("Attr = 0x%x\n", DirEntry->Attr);
752 TRACE("StartCluster = 0x%x\n", DirEntry->StartCluster);
753 TRACE("Size = %d\n", DirEntry->Size);
754 TRACE("Time = %d\n", DirEntry->Time);
755 TRACE("Date = %d\n", DirEntry->Date);
756 TRACE("CreateTime = %d\n", DirEntry->CreateTime);
757 TRACE("CreateDate = %d\n", DirEntry->CreateDate);
758 TRACE("LastAccessTime = %d\n", DirEntry->LastAccessTime);
759 TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
760
761 return TRUE;
762 }
763 }
764
765 return FALSE;
766}
struct FATX_DIRENTRY * PFATX_DIRENTRY
VOID FatSwapFatXDirEntry(PFATX_DIRENTRY Obj)
Definition: fat.c:126
Dirent FileNameLen
Definition: dirsup.c:506
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by FatLookupFile().

Variable Documentation

◆ DirectoryBufferListHead

LIST_ENTRY DirectoryBufferListHead = {&DirectoryBufferListHead, &DirectoryBufferListHead}

Definition at line 417 of file fat.c.

Referenced by FatBufferDirectory().

◆ FatFuncTable

const DEVVTBL FatFuncTable
Initial value:
=
{
L"fastfat",
}
ARC_STATUS FatOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fat.c:1420
ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fat.c:1481
ARC_STATUS FatRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fat.c:1462
ARC_STATUS FatGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fat.c:1406
ARC_STATUS FatClose(ULONG FileId)
Definition: fat.c:1397
#define L(x)
Definition: ntvdm.h:50

Definition at line 1543 of file fat.c.

Referenced by FatMount().

◆ FatVolumes

Definition at line 58 of file fat.c.

Referenced by FatMount(), and FatOpen().

◆ FatXFuncTable

const DEVVTBL FatXFuncTable
Initial value:

Definition at line 1553 of file fat.c.

Referenced by FatMount().