ReactOS 0.4.15-dev-7906-g1b85a5f
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:1125
static ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, UINT32 StartCluster)
Definition: fat.c:1041
BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: fat.c:1360
#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 1394 of file fat.c.

1395{
1397
1399
1400 return ESUCCESS;
1401}
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:418
#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 1041 of file fat.c.

1042{
1043 ULONG ClusterCount = 0;
1044
1045 TRACE("FatCountClustersInChain() StartCluster = %d\n", StartCluster);
1046
1047 while (1)
1048 {
1049 //
1050 // If end of chain then break out of our cluster counting loop
1051 //
1052 if (FAT_IS_END_CLUSTER(StartCluster))
1053 {
1054 break;
1055 }
1056
1057 //
1058 // Increment count
1059 //
1060 ClusterCount++;
1061
1062 //
1063 // Get next cluster
1064 //
1065 if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
1066 {
1067 return 0;
1068 }
1069 }
1070
1071 TRACE("FatCountClustersInChain() ClusterCount = %d\n", ClusterCount);
1072
1073 return ClusterCount;
1074}
static BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, UINT32 Cluster, PUINT32 ClusterPointer)
Definition: fat.c:951
#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 951 of file fat.c.

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

914{
915 UINT32 SectorNumAbsolute = Volume->ActiveFatSectorStart + FatSectorNumber;
916 UINT32 CacheIndex = FatSectorNumber % Volume->FatCacheSize;
917
918 ASSERT(FatSectorNumber < Volume->SectorsPerFat);
919
920 // cache miss
921 if (Volume->FatCacheIndex[CacheIndex] != SectorNumAbsolute)
922 {
923 UINT32 SectorsToRead = min(Volume->FatCacheSize - CacheIndex, min(Volume->SectorsPerFat - SectorNumAbsolute, 4));
924 UINT8 i;
925
926 if (!FatReadVolumeSectors(Volume, SectorNumAbsolute, SectorsToRead, &Volume->FatCache[CacheIndex * Volume->BytesPerSector]))
927 {
928 return NULL;
929 }
930
931 for (i = 0; i < SectorsToRead; i++)
932 {
933 Volume->FatCacheIndex[CacheIndex + i] = SectorNumAbsolute + i;
934 }
935
936 TRACE("FAT cache miss: read sector 0x%x from disk\n", SectorNumAbsolute);
937 }
938 else
939 {
940 TRACE("FAT cache hit: sector 0x%x present\n", SectorNumAbsolute);
941 }
942
943 return &Volume->FatCache[CacheIndex * Volume->BytesPerSector];
944}
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 1403 of file fat.c.

1404{
1406
1408 Information->EndingAddress.LowPart = FileHandle->FileSize;
1409 Information->CurrentAddress.LowPart = FileHandle->FilePointer;
1410
1411 TRACE("FatGetFileInformation(%lu) -> FileSize = %lu, FilePointer = 0x%lx\n",
1412 FileId, Information->EndingAddress.LowPart, Information->CurrentAddress.LowPart);
1413
1414 return ESUCCESS;
1415}
#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 //
789 // Figure out how many sub-directories we are nested in
790 //
791 NumberOfPathParts = FsGetNumPathParts(FileName);
792
793 //
794 // Loop once for each part
795 //
796 for (i=0; i<NumberOfPathParts; i++)
797 {
798 //
799 // Get first path part
800 //
802
803 //
804 // Advance to the next part of the path
805 //
806 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
807 {
808 }
809 FileName++;
810
811 //
812 // Buffer the directory contents
813 //
814 DirectoryBuffer = FatBufferDirectory(Volume, DirectoryStartCluster, &DirectorySize, (i == 0) );
815 if (DirectoryBuffer == NULL)
816 {
817 return ENOMEM;
818 }
819
820 //
821 // Search for file name in directory
822 //
823 if (ISFATX(Volume->FatType))
824 {
825 if (!FatXSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
826 {
827 return ENOENT;
828 }
829 }
830 else
831 {
832 if (!FatSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
833 {
834 return ENOENT;
835 }
836 }
837
838 //
839 // If we have another sub-directory to go then
840 // grab the start cluster and free the fat chain array
841 //
842 if ((i+1) < NumberOfPathParts)
843 {
844 //
845 // Check if current entry is a directory
846 //
847 if (!(FatFileInfo.Attributes & ATTR_DIRECTORY))
848 {
849 return ENOTDIR;
850 }
851 DirectoryStartCluster = FatFileInfo.StartCluster;
852 }
853 }
854
855 RtlCopyMemory(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
856
857 return ESUCCESS;
858}
#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:330
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:358
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
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 1560 of file fat.c.

1561{
1563 UCHAR Buffer[512];
1569 ULONG Count;
1572
1573 TRACE("Enter FatMount(%lu)\n", DeviceId);
1574
1575 //
1576 // Allocate data for volume information
1577 //
1579 if (!Volume)
1580 return NULL;
1582
1583 //
1584 // Read the BootSector
1585 //
1586 Position.QuadPart = 0;
1587 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1588 if (Status != ESUCCESS)
1589 {
1591 return NULL;
1592 }
1593 Status = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count);
1594 if (Status != ESUCCESS || Count != sizeof(Buffer))
1595 {
1597 return NULL;
1598 }
1599
1600 //
1601 // Check if BootSector is valid. If no, return early
1602 //
1603 if (!RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) &&
1604 !RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) &&
1605 !RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) &&
1606 !RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4))
1607 {
1609 return NULL;
1610 }
1611
1612 //
1613 // Determine sector count
1614 //
1616 if (Status != ESUCCESS)
1617 {
1619 return NULL;
1620 }
1621 SectorCount.QuadPart = (FileInformation.EndingAddress.QuadPart - FileInformation.StartingAddress.QuadPart);
1622 SectorCount.QuadPart /= SECTOR_SIZE;
1623
1624 //
1625 // Keep device id
1626 //
1627 Volume->DeviceId = DeviceId;
1628
1629 //
1630 // Really open the volume
1631 //
1632 if (!FatOpenVolume(Volume, BootSector, SectorCount.QuadPart))
1633 {
1635 return NULL;
1636 }
1637
1638 //
1639 // Remember FAT volume information
1640 //
1641 FatVolumes[DeviceId] = Volume;
1642
1643 //
1644 // Return success
1645 //
1646 TRACE("FatMount(%lu) success\n", DeviceId);
1647 return (ISFATX(Volume->FatType) ? &FatXFuncTable : &FatFuncTable);
1648}
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:252
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:245
#define SECTOR_SIZE
Definition: fs.h:22
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:238
#define TAG_FAT_VOLUME
Definition: fat.c:33
const DEVVTBL FatXFuncTable
Definition: fat.c:1550
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:1540
Definition: bufpool.h:45
Status
Definition: gdiplustypes.h:25
#define RtlEqualMemory(a, b, c)
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 1417 of file fat.c.

1418{
1419 PFAT_VOLUME_INFO FatVolume;
1420 FAT_FILE_INFO TempFileInfo;
1422 ULONG DeviceId;
1425
1426 if (OpenMode != OpenReadOnly && OpenMode != OpenDirectory)
1427 return EACCES;
1428
1429 DeviceId = FsGetDeviceId(*FileId);
1430 FatVolume = FatVolumes[DeviceId];
1431
1432 TRACE("FatOpen() FileName = %s\n", Path);
1433
1434 RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo));
1435 Status = FatLookupFile(FatVolume, Path, &TempFileInfo);
1436 if (Status != ESUCCESS)
1437 return ENOENT;
1438
1439 //
1440 // Check if caller opened what he expected (dir vs file)
1441 //
1442 IsDirectory = (TempFileInfo.Attributes & ATTR_DIRECTORY) != 0;
1443 if (IsDirectory && OpenMode != OpenDirectory)
1444 return EISDIR;
1445 else if (!IsDirectory && OpenMode != OpenReadOnly)
1446 return ENOTDIR;
1447
1449 if (!FileHandle)
1450 return ENOMEM;
1451
1452 RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO));
1453 FileHandle->Volume = FatVolume;
1454
1456 return ESUCCESS;
1457}
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
#define EACCES
Definition: acclib.h:85
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:425
VOID FsSetDeviceSpecific(ULONG FileId, VOID *Specific)
Definition: fs.c:411
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:261
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 866 of file fat.c.

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

Referenced by FatSearchDirectoryBufferForFile().

◆ FatRead()

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

Definition at line 1459 of file fat.c.

1460{
1463
1464 //
1465 // Call old read method
1466 //
1468
1469 //
1470 // Check for success
1471 //
1472 if (Success)
1473 return ESUCCESS;
1474 else
1475 return EIO;
1476}
#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:1196
@ 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 1077 of file fat.c.

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

Referenced by FatReadClusterChain().

◆ FatReadClusterChain()

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

Definition at line 1125 of file fat.c.

1126{
1127 UINT32 ClustersRead, NextClusterNumber, ClustersLeft = NumberOfClusters;
1128
1129 TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
1130
1131 ASSERT(NumberOfClusters > 0);
1132
1133 while (FatReadAdjacentClusters(Volume, StartClusterNumber, ClustersLeft, Buffer, &ClustersRead, &NextClusterNumber))
1134 {
1135 ClustersLeft -= ClustersRead;
1136 Buffer = (PVOID)((ULONG_PTR)Buffer + (ClustersRead * Volume->SectorsPerCluster * Volume->BytesPerSector));
1137 StartClusterNumber = NextClusterNumber;
1138 }
1139
1140 if (LastClusterNumber)
1141 {
1142 *LastClusterNumber = NextClusterNumber;
1143 }
1144
1145 return (ClustersRead > 0);
1146}
static BOOLEAN FatReadAdjacentClusters(PFAT_VOLUME_INFO Volume, UINT32 StartClusterNumber, UINT32 MaxClusters, PVOID Buffer, PUINT32 ClustersRead, PUINT32 LastClusterNumber)
Definition: fat.c:1077
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 1196 of file fat.c.

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

1153{
1154 ULONG ClusterStartSector;
1155 ULONG SectorOffset, ReadSize, SectorCount;
1158
1159 //TRACE("FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer);
1160
1161 ClusterStartSector = ((ClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
1162
1163 // This is the offset of the data in sectors
1164 SectorOffset = (StartingOffset / Volume->BytesPerSector);
1165 StartingOffset %= Volume->BytesPerSector;
1166
1167 // Calculate how many sectors we need to read
1168 SectorCount = (StartingOffset + Length + Volume->BytesPerSector - 1) / Volume->BytesPerSector;
1169
1170 // Calculate rounded up read size
1171 ReadSize = SectorCount * Volume->BytesPerSector;
1172
1174 if (!ReadBuffer)
1175 {
1176 return FALSE;
1177 }
1178
1179 if (FatReadVolumeSectors(Volume, ClusterStartSector + SectorOffset, SectorCount, ReadBuffer))
1180 {
1182 Success = TRUE;
1183 }
1184
1186
1187 return Success;
1188}
_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 1360 of file fat.c.

1361{
1363 ULONG Count;
1365
1366 //TRACE("FatReadVolumeSectors(): SectorNumber %d, SectorCount %d, Buffer %p\n",
1367 // SectorNumber, SectorCount, Buffer);
1368
1369 //
1370 // Seek to right position
1371 //
1372 Position.QuadPart = (ULONGLONG)SectorNumber * 512;
1373 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
1374 if (Status != ESUCCESS)
1375 {
1376 TRACE("FatReadVolumeSectors() Failed to seek\n");
1377 return FALSE;
1378 }
1379
1380 //
1381 // Read data
1382 //
1383 Status = ArcRead(Volume->DeviceId, Buffer, SectorCount * 512, &Count);
1384 if (Status != ESUCCESS || Count != SectorCount * 512)
1385 {
1386 TRACE("FatReadVolumeSectors() Failed to read\n");
1387 return FALSE;
1388 }
1389
1390 // Return success
1391 return TRUE;
1392}
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 // We found the entry, now fill in the FAT_FILE_INFO struct
674 //
675 FatFileInfoPointer->Attributes = DirEntry->Attr;
676 FatFileInfoPointer->FileSize = DirEntry->Size;
677 FatFileInfoPointer->FilePointer = 0;
678 StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
679 FatFileInfoPointer->CurrentCluster = StartCluster;
680 FatFileInfoPointer->StartCluster = StartCluster;
681
682 TRACE("MSDOS Directory Entry:\n");
683 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]);
684 TRACE("Attr = 0x%x\n", DirEntry->Attr);
685 TRACE("ReservedNT = 0x%x\n", DirEntry->ReservedNT);
686 TRACE("TimeInTenths = %d\n", DirEntry->TimeInTenths);
687 TRACE("CreateTime = %d\n", DirEntry->CreateTime);
688 TRACE("CreateDate = %d\n", DirEntry->CreateDate);
689 TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
690 TRACE("ClusterHigh = 0x%x\n", DirEntry->ClusterHigh);
691 TRACE("Time = %d\n", DirEntry->Time);
692 TRACE("Date = %d\n", DirEntry->Date);
693 TRACE("ClusterLow = 0x%x\n", DirEntry->ClusterLow);
694 TRACE("Size = %d\n", DirEntry->Size);
695 TRACE("StartCluster = 0x%x\n", StartCluster);
696
697 return TRUE;
698 }
699
700 //
701 // Nope, no match - zero buffers and continue looking
702 //
703 RtlZeroMemory(ShortNameBuffer, 13 * sizeof(UCHAR));
704 RtlZeroMemory(LfnNameBuffer, 261 * sizeof(UCHAR));
705 continue;
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:866
#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 1478 of file fat.c.

1479{
1482 LARGE_INTEGER NewPosition = *Position;
1483
1484 switch (SeekMode)
1485 {
1486 case SeekAbsolute:
1487 break;
1488 case SeekRelative:
1489 NewPosition.QuadPart += (ULONGLONG)FileHandle->FilePointer;
1490 break;
1491 default:
1492 ASSERT(FALSE);
1493 return EINVAL;
1494 }
1495
1496 if (NewPosition.HighPart != 0)
1497 return EINVAL;
1498 if (NewPosition.LowPart >= FileHandle->FileSize)
1499 return EINVAL;
1500
1501 TRACE("FatSeek() NewPosition = %u, OldPointer = %u, SeekMode = %d\n", NewPosition.LowPart, FileHandle->FilePointer, SeekMode);
1502
1503 {
1504 UINT32 OldClusterIdx = FileHandle->FilePointer / (Volume->SectorsPerCluster * Volume->BytesPerSector);
1505 UINT32 NewClusterIdx = NewPosition.LowPart / (Volume->SectorsPerCluster * Volume->BytesPerSector);
1506
1507 TRACE("FatSeek() OldClusterIdx: %u, NewClusterIdx: %u\n", OldClusterIdx, NewClusterIdx);
1508
1509 if (NewClusterIdx != OldClusterIdx)
1510 {
1511 UINT32 CurrentClusterIdx, ClusterNumber;
1512
1513 if (NewClusterIdx > OldClusterIdx)
1514 {
1515 CurrentClusterIdx = OldClusterIdx;
1516 ClusterNumber = FileHandle->CurrentCluster;
1517 }
1518 else
1519 {
1520 CurrentClusterIdx = 0;
1521 ClusterNumber = FileHandle->StartCluster;
1522 }
1523
1524 for (; CurrentClusterIdx < NewClusterIdx; CurrentClusterIdx++)
1525 {
1526 if (!FatGetFatEntry(Volume, ClusterNumber, &ClusterNumber))
1527 {
1528 return EIO;
1529 }
1530 }
1531 FileHandle->CurrentCluster = ClusterNumber;
1532 }
1533 }
1534
1535 FileHandle->FilePointer = NewPosition.LowPart;
1536
1537 return ESUCCESS;
1538}
#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:1417
ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fat.c:1478
ARC_STATUS FatRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fat.c:1459
ARC_STATUS FatGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fat.c:1403
ARC_STATUS FatClose(ULONG FileId)
Definition: fat.c:1394
#define L(x)
Definition: ntvdm.h:50

Definition at line 1540 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 1550 of file fat.c.

Referenced by FatMount().