ReactOS  0.4.13-dev-259-g5ca9c9c
fat.c
Go to the documentation of this file.
1 /*
2  * FreeLoader
3  * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4  * Copyright (C) 2009 Hervé Poussineau
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <freeldr.h>
22 
23 #include <debug.h>
24 
25 DBG_DEFAULT_CHANNEL(FILESYSTEM);
26 
28 PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG* EntryCountPointer, BOOLEAN RootDirectory);
29 BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
32 BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG* ClusterPointer);
35 BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer);
38 
39 #define TAG_FAT_CHAIN 'CtaT'
40 #define TAG_FAT_FILE 'FtaF'
41 #define TAG_FAT_VOLUME 'VtaF'
42 #define TAG_FAT_BUFFER 'BtaF'
43 
44 typedef struct _FAT_VOLUME_INFO
45 {
46  ULONG BytesPerSector; /* Number of bytes per sector */
47  ULONG SectorsPerCluster; /* Number of sectors per cluster */
48  ULONG FatSectorStart; /* Starting sector of 1st FAT table */
49  ULONG ActiveFatSectorStart; /* Starting sector of active FAT table */
50  ULONG NumberOfFats; /* Number of FAT tables */
51  ULONG SectorsPerFat; /* Sectors per FAT table */
52  ULONG RootDirSectorStart; /* Starting sector of the root directory (non-fat32) */
53  ULONG RootDirSectors; /* Number of sectors of the root directory (non-fat32) */
54  ULONG RootDirStartCluster; /* Starting cluster number of the root directory (fat32 only) */
55  ULONG DataSectorStart; /* Starting sector of the data area */
56  ULONG FatType; /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
59 
61 
63 {
64  SW(Obj, BytesPerSector);
65  SW(Obj, ReservedSectors);
66  SW(Obj, RootDirEntries);
67  SW(Obj, TotalSectors);
68  SW(Obj, SectorsPerFat);
71  SD(Obj, HiddenSectors);
72  SD(Obj, TotalSectorsBig);
73  SD(Obj, VolumeSerialNumber);
74  SW(Obj, BootSectorMagic);
75 }
76 
78 {
79  SW(Obj, BytesPerSector);
80  SW(Obj, ReservedSectors);
81  SW(Obj, RootDirEntries);
82  SW(Obj, TotalSectors);
83  SW(Obj, SectorsPerFat);
85  SD(Obj, HiddenSectors);
86  SD(Obj, TotalSectorsBig);
87  SD(Obj, SectorsPerFatBig);
88  SW(Obj, ExtendedFlags);
89  SW(Obj, FileSystemVersion);
90  SD(Obj, RootDirStartCluster);
91  SW(Obj, FsInfo);
93  SD(Obj, VolumeSerialNumber);
94  SW(Obj, BootSectorMagic);
95 }
96 
98 {
99  SD(Obj, VolumeSerialNumber);
100  SD(Obj, SectorsPerCluster);
101  SW(Obj, NumberOfFats);
102 }
103 
105 {
106  SW(Obj, CreateTime);
107  SW(Obj, CreateDate);
108  SW(Obj, LastAccessDate);
109  SW(Obj, ClusterHigh);
110  SW(Obj, Time);
111  SW(Obj, Date);
112  SW(Obj, ClusterLow);
113  SD(Obj, Size);
114 }
115 
117 {
118  int i;
119  SW(Obj, StartCluster);
120  for(i = 0; i < 5; i++)
121  Obj->Name0_4[i] = SWAPW(Obj->Name0_4[i]);
122  for(i = 0; i < 6; i++)
123  Obj->Name5_10[i] = SWAPW(Obj->Name5_10[i]);
124  for(i = 0; i < 2; i++)
125  Obj->Name11_12[i] = SWAPW(Obj->Name11_12[i]);
126 }
127 
129 {
130  SD(Obj, StartCluster);
131  SD(Obj, Size);
132  SW(Obj, Time);
133  SW(Obj, Date);
134  SW(Obj, CreateTime);
135  SW(Obj, CreateDate);
136  SW(Obj, LastAccessTime);
137  SW(Obj, LastAccessDate);
138 }
139 
141 {
142  char ErrMsg[80];
143  ULONG FatSize;
144  PFAT_BOOTSECTOR FatVolumeBootSector;
145  PFAT32_BOOTSECTOR Fat32VolumeBootSector;
146  PFATX_BOOTSECTOR FatXVolumeBootSector;
147 
148  TRACE("FatOpenVolume() DeviceId = %d\n", Volume->DeviceId);
149 
150  //
151  // Allocate the memory to hold the boot sector
152  //
153  FatVolumeBootSector = (PFAT_BOOTSECTOR)BootSector;
154  Fat32VolumeBootSector = (PFAT32_BOOTSECTOR)BootSector;
155  FatXVolumeBootSector = (PFATX_BOOTSECTOR)BootSector;
156 
157  // Get the FAT type
158  Volume->FatType = FatDetermineFatType(FatVolumeBootSector, PartitionSectorCount);
159 
160  // Dump boot sector (and swap it for big endian systems)
161  TRACE("Dumping boot sector:\n");
162  if (ISFATX(Volume->FatType))
163  {
164  FatSwapFatXBootSector(FatXVolumeBootSector);
165  TRACE("sizeof(FATX_BOOTSECTOR) = 0x%x.\n", sizeof(FATX_BOOTSECTOR));
166 
167  TRACE("FileSystemType: %c%c%c%c.\n", FatXVolumeBootSector->FileSystemType[0], FatXVolumeBootSector->FileSystemType[1], FatXVolumeBootSector->FileSystemType[2], FatXVolumeBootSector->FileSystemType[3]);
168  TRACE("VolumeSerialNumber: 0x%x\n", FatXVolumeBootSector->VolumeSerialNumber);
169  TRACE("SectorsPerCluster: %d\n", FatXVolumeBootSector->SectorsPerCluster);
170  TRACE("NumberOfFats: %d\n", FatXVolumeBootSector->NumberOfFats);
171  TRACE("Unknown: 0x%x\n", FatXVolumeBootSector->Unknown);
172 
173  TRACE("FatType %s\n", Volume->FatType == FATX16 ? "FATX16" : "FATX32");
174 
175  }
176  else if (Volume->FatType == FAT32)
177  {
178  FatSwapFat32BootSector(Fat32VolumeBootSector);
179  TRACE("sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR));
180 
181  TRACE("JumpBoot: 0x%x 0x%x 0x%x\n", Fat32VolumeBootSector->JumpBoot[0], Fat32VolumeBootSector->JumpBoot[1], Fat32VolumeBootSector->JumpBoot[2]);
182  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]);
183  TRACE("BytesPerSector: %d\n", Fat32VolumeBootSector->BytesPerSector);
184  TRACE("SectorsPerCluster: %d\n", Fat32VolumeBootSector->SectorsPerCluster);
185  TRACE("ReservedSectors: %d\n", Fat32VolumeBootSector->ReservedSectors);
186  TRACE("NumberOfFats: %d\n", Fat32VolumeBootSector->NumberOfFats);
187  TRACE("RootDirEntries: %d\n", Fat32VolumeBootSector->RootDirEntries);
188  TRACE("TotalSectors: %d\n", Fat32VolumeBootSector->TotalSectors);
189  TRACE("MediaDescriptor: 0x%x\n", Fat32VolumeBootSector->MediaDescriptor);
190  TRACE("SectorsPerFat: %d\n", Fat32VolumeBootSector->SectorsPerFat);
191  TRACE("SectorsPerTrack: %d\n", Fat32VolumeBootSector->SectorsPerTrack);
192  TRACE("NumberOfHeads: %d\n", Fat32VolumeBootSector->NumberOfHeads);
193  TRACE("HiddenSectors: %d\n", Fat32VolumeBootSector->HiddenSectors);
194  TRACE("TotalSectorsBig: %d\n", Fat32VolumeBootSector->TotalSectorsBig);
195  TRACE("SectorsPerFatBig: %d\n", Fat32VolumeBootSector->SectorsPerFatBig);
196  TRACE("ExtendedFlags: 0x%x\n", Fat32VolumeBootSector->ExtendedFlags);
197  TRACE("FileSystemVersion: 0x%x\n", Fat32VolumeBootSector->FileSystemVersion);
198  TRACE("RootDirStartCluster: %d\n", Fat32VolumeBootSector->RootDirStartCluster);
199  TRACE("FsInfo: %d\n", Fat32VolumeBootSector->FsInfo);
200  TRACE("BackupBootSector: %d\n", Fat32VolumeBootSector->BackupBootSector);
201  TRACE("Reserved: 0x%x\n", Fat32VolumeBootSector->Reserved);
202  TRACE("DriveNumber: 0x%x\n", Fat32VolumeBootSector->DriveNumber);
203  TRACE("Reserved1: 0x%x\n", Fat32VolumeBootSector->Reserved1);
204  TRACE("BootSignature: 0x%x\n", Fat32VolumeBootSector->BootSignature);
205  TRACE("VolumeSerialNumber: 0x%x\n", Fat32VolumeBootSector->VolumeSerialNumber);
206  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]);
207  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]);
208  TRACE("BootSectorMagic: 0x%x\n", Fat32VolumeBootSector->BootSectorMagic);
209  }
210  else
211  {
212  FatSwapFatBootSector(FatVolumeBootSector);
213  TRACE("sizeof(FAT_BOOTSECTOR) = 0x%x.\n", sizeof(FAT_BOOTSECTOR));
214 
215  TRACE("JumpBoot: 0x%x 0x%x 0x%x\n", FatVolumeBootSector->JumpBoot[0], FatVolumeBootSector->JumpBoot[1], FatVolumeBootSector->JumpBoot[2]);
216  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]);
217  TRACE("BytesPerSector: %d\n", FatVolumeBootSector->BytesPerSector);
218  TRACE("SectorsPerCluster: %d\n", FatVolumeBootSector->SectorsPerCluster);
219  TRACE("ReservedSectors: %d\n", FatVolumeBootSector->ReservedSectors);
220  TRACE("NumberOfFats: %d\n", FatVolumeBootSector->NumberOfFats);
221  TRACE("RootDirEntries: %d\n", FatVolumeBootSector->RootDirEntries);
222  TRACE("TotalSectors: %d\n", FatVolumeBootSector->TotalSectors);
223  TRACE("MediaDescriptor: 0x%x\n", FatVolumeBootSector->MediaDescriptor);
224  TRACE("SectorsPerFat: %d\n", FatVolumeBootSector->SectorsPerFat);
225  TRACE("SectorsPerTrack: %d\n", FatVolumeBootSector->SectorsPerTrack);
226  TRACE("NumberOfHeads: %d\n", FatVolumeBootSector->NumberOfHeads);
227  TRACE("HiddenSectors: %d\n", FatVolumeBootSector->HiddenSectors);
228  TRACE("TotalSectorsBig: %d\n", FatVolumeBootSector->TotalSectorsBig);
229  TRACE("DriveNumber: 0x%x\n", FatVolumeBootSector->DriveNumber);
230  TRACE("Reserved1: 0x%x\n", FatVolumeBootSector->Reserved1);
231  TRACE("BootSignature: 0x%x\n", FatVolumeBootSector->BootSignature);
232  TRACE("VolumeSerialNumber: 0x%x\n", FatVolumeBootSector->VolumeSerialNumber);
233  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]);
234  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]);
235  TRACE("BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic);
236  }
237 
238  //
239  // Check the boot sector magic
240  //
241  if (! ISFATX(Volume->FatType) && FatVolumeBootSector->BootSectorMagic != 0xaa55)
242  {
243  sprintf(ErrMsg, "Invalid boot sector magic (expected 0xaa55 found 0x%x)",
244  FatVolumeBootSector->BootSectorMagic);
245  FileSystemError(ErrMsg);
246  return FALSE;
247  }
248 
249  //
250  // Check the FAT cluster size
251  // We do not support clusters bigger than 64k
252  //
253  if ((ISFATX(Volume->FatType) && 64 * 1024 < FatXVolumeBootSector->SectorsPerCluster * 512) ||
254  (! ISFATX(Volume->FatType) && 64 * 1024 < FatVolumeBootSector->SectorsPerCluster * FatVolumeBootSector->BytesPerSector))
255  {
256  FileSystemError("This file system has cluster sizes bigger than 64k.\nFreeLoader does not support this.");
257  return FALSE;
258  }
259 
260  //
261  // Get the sectors per FAT,
262  // root directory starting sector,
263  // and data sector start
264  //
265  if (ISFATX(Volume->FatType))
266  {
267  Volume->BytesPerSector = 512;
268  Volume->SectorsPerCluster = SWAPD(FatXVolumeBootSector->SectorsPerCluster);
269  Volume->FatSectorStart = (4096 / Volume->BytesPerSector);
270  Volume->ActiveFatSectorStart = Volume->FatSectorStart;
271  Volume->NumberOfFats = 1;
272  FatSize = (ULONG)(PartitionSectorCount / Volume->SectorsPerCluster *
273  (Volume->FatType == FATX16 ? 2 : 4));
274  Volume->SectorsPerFat = (((FatSize + 4095) / 4096) * 4096) / Volume->BytesPerSector;
275 
276  Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
277  Volume->RootDirSectors = FatXVolumeBootSector->SectorsPerCluster;
278 
279  Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
280  }
281  else if (Volume->FatType != FAT32)
282  {
283  Volume->BytesPerSector = FatVolumeBootSector->BytesPerSector;
284  Volume->SectorsPerCluster = FatVolumeBootSector->SectorsPerCluster;
285  Volume->FatSectorStart = FatVolumeBootSector->ReservedSectors;
286  Volume->ActiveFatSectorStart = Volume->FatSectorStart;
287  Volume->NumberOfFats = FatVolumeBootSector->NumberOfFats;
288  Volume->SectorsPerFat = FatVolumeBootSector->SectorsPerFat;
289 
290  Volume->RootDirSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
291  Volume->RootDirSectors = ((FatVolumeBootSector->RootDirEntries * 32) + (Volume->BytesPerSector - 1)) / Volume->BytesPerSector;
292 
293  Volume->DataSectorStart = Volume->RootDirSectorStart + Volume->RootDirSectors;
294  }
295  else
296  {
297  Volume->BytesPerSector = Fat32VolumeBootSector->BytesPerSector;
298  Volume->SectorsPerCluster = Fat32VolumeBootSector->SectorsPerCluster;
299  Volume->FatSectorStart = Fat32VolumeBootSector->ReservedSectors;
300  Volume->ActiveFatSectorStart = Volume->FatSectorStart +
301  ((Fat32VolumeBootSector->ExtendedFlags & 0x80) ? ((Fat32VolumeBootSector->ExtendedFlags & 0x0f) * Fat32VolumeBootSector->SectorsPerFatBig) : 0);
302  Volume->NumberOfFats = Fat32VolumeBootSector->NumberOfFats;
303  Volume->SectorsPerFat = Fat32VolumeBootSector->SectorsPerFatBig;
304 
305  Volume->RootDirStartCluster = Fat32VolumeBootSector->RootDirStartCluster;
306  Volume->DataSectorStart = Volume->FatSectorStart + Volume->NumberOfFats * Volume->SectorsPerFat;
307 
308  //
309  // Check version
310  // we only work with version 0
311  //
312  if (Fat32VolumeBootSector->FileSystemVersion != 0)
313  {
314  FileSystemError("FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
315  return FALSE;
316  }
317  }
318 
319  return TRUE;
320 }
321 
323 {
324  ULONG RootDirSectors;
325  ULONG DataSectorCount;
326  ULONG SectorsPerFat;
327  ULONG TotalSectors;
328  ULONG CountOfClusters;
329  PFAT32_BOOTSECTOR Fat32BootSector = (PFAT32_BOOTSECTOR)FatBootSector;
330  PFATX_BOOTSECTOR FatXBootSector = (PFATX_BOOTSECTOR)FatBootSector;
331 
332  if (0 == strncmp(FatXBootSector->FileSystemType, "FATX", 4))
333  {
334  CountOfClusters = (ULONG)(PartitionSectorCount / FatXBootSector->SectorsPerCluster);
335  if (CountOfClusters < 65525)
336  {
337  /* Volume is FATX16 */
338  return FATX16;
339  }
340  else
341  {
342  /* Volume is FAT32 */
343  return FATX32;
344  }
345  }
346  else
347  {
348  RootDirSectors = ((SWAPW(FatBootSector->RootDirEntries) * 32) + (SWAPW(FatBootSector->BytesPerSector) - 1)) / SWAPW(FatBootSector->BytesPerSector);
349  SectorsPerFat = SWAPW(FatBootSector->SectorsPerFat) ? SWAPW(FatBootSector->SectorsPerFat) : SWAPD(Fat32BootSector->SectorsPerFatBig);
350  TotalSectors = SWAPW(FatBootSector->TotalSectors) ? SWAPW(FatBootSector->TotalSectors) : SWAPD(FatBootSector->TotalSectorsBig);
351  DataSectorCount = TotalSectors - (SWAPW(FatBootSector->ReservedSectors) + (FatBootSector->NumberOfFats * SectorsPerFat) + RootDirSectors);
352 
353 //mjl
354  if (FatBootSector->SectorsPerCluster == 0)
355  CountOfClusters = 0;
356  else
357  CountOfClusters = DataSectorCount / FatBootSector->SectorsPerCluster;
358 
359  if (CountOfClusters < 4085)
360  {
361  /* Volume is FAT12 */
362  return FAT12;
363  }
364  else if (CountOfClusters < 65525)
365  {
366  /* Volume is FAT16 */
367  return FAT16;
368  }
369  else
370  {
371  /* Volume is FAT32 */
372  return FAT32;
373  }
374  }
375 }
376 
377 typedef struct _DIRECTORY_BUFFER
378 {
385 
387 
389 {
390  PDIRECTORY_BUFFER DirectoryBuffer;
392 
393  TRACE("FatBufferDirectory() DirectoryStartCluster = %d RootDirectory = %s\n", DirectoryStartCluster, (RootDirectory ? "TRUE" : "FALSE"));
394 
395  /*
396  * For FAT32, the root directory is nothing special. We can treat it the same
397  * as a subdirectory.
398  */
399  if (RootDirectory && Volume->FatType == FAT32)
400  {
401  DirectoryStartCluster = Volume->RootDirStartCluster;
403  }
404 
405  /* Search the list for a match */
408  Entry = Entry->Flink)
409  {
410  DirectoryBuffer = CONTAINING_RECORD(Entry, DIRECTORY_BUFFER, Link);
411 
412  /* Check if it matches */
413  if ((DirectoryBuffer->Volume == Volume) &&
414  (DirectoryBuffer->DirectoryStartCluster == DirectoryStartCluster))
415  {
416  TRACE("Found cached buffer\n");
417  *DirectorySize = DirectoryBuffer->DirectorySize;
418  return DirectoryBuffer->Data;
419  }
420  }
421 
422  //
423  // Calculate the size of the directory
424  //
425  if (RootDirectory)
426  {
427  *DirectorySize = Volume->RootDirSectors * Volume->BytesPerSector;
428  }
429  else
430  {
431  *DirectorySize = FatCountClustersInChain(Volume, DirectoryStartCluster) * Volume->SectorsPerCluster * Volume->BytesPerSector;
432  }
433 
434  //
435  // Attempt to allocate memory for directory buffer
436  //
437  TRACE("Trying to allocate (DirectorySize) %d bytes.\n", *DirectorySize);
438  DirectoryBuffer = FrLdrTempAlloc(*DirectorySize + sizeof(DIRECTORY_BUFFER),
440 
441  if (DirectoryBuffer == NULL)
442  {
443  return NULL;
444  }
445 
446  //
447  // Now read directory contents into DirectoryBuffer
448  //
449  if (RootDirectory)
450  {
451  if (!FatReadVolumeSectors(Volume, Volume->RootDirSectorStart, Volume->RootDirSectors, DirectoryBuffer->Data))
452  {
453  FrLdrTempFree(DirectoryBuffer, TAG_FAT_BUFFER);
454  return NULL;
455  }
456  }
457  else
458  {
459  if (!FatReadClusterChain(Volume, DirectoryStartCluster, 0xFFFFFFFF, DirectoryBuffer->Data))
460  {
461  FrLdrTempFree(DirectoryBuffer, TAG_FAT_BUFFER);
462  return NULL;
463  }
464  }
465 
466  /* Enqueue it in the list */
467  DirectoryBuffer->Volume = Volume;
468  DirectoryBuffer->DirectoryStartCluster = DirectoryStartCluster;
469  DirectoryBuffer->DirectorySize = *DirectorySize;
470  InsertTailList(&DirectoryBufferListHead, &DirectoryBuffer->Link);
471 
472  return DirectoryBuffer->Data;
473 }
474 
476 {
477  ULONG EntryCount;
478  ULONG CurrentEntry;
479  CHAR LfnNameBuffer[265];
480  CHAR ShortNameBuffer[20];
481  ULONG StartCluster;
482  DIRENTRY OurDirEntry;
483  LFN_DIRENTRY OurLfnDirEntry;
484  PDIRENTRY DirEntry = &OurDirEntry;
485  PLFN_DIRENTRY LfnDirEntry = &OurLfnDirEntry;
486 
487  EntryCount = DirectorySize / sizeof(DIRENTRY);
488 
489  TRACE("FatSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName);
490 
491  memset(ShortNameBuffer, 0, 13 * sizeof(CHAR));
492  memset(LfnNameBuffer, 0, 261 * sizeof(CHAR));
493 
494  for (CurrentEntry=0; CurrentEntry<EntryCount; CurrentEntry++, DirectoryBuffer = ((PDIRENTRY)DirectoryBuffer)+1)
495  {
496  OurLfnDirEntry = *((PLFN_DIRENTRY) DirectoryBuffer);
497  FatSwapLFNDirEntry(LfnDirEntry);
498  OurDirEntry = *((PDIRENTRY) DirectoryBuffer);
500 
501  //TRACE("Dumping directory entry %d:\n", CurrentEntry);
502  //DbgDumpBuffer(DPRINT_FILESYSTEM, DirEntry, sizeof(DIRENTRY));
503 
504  //
505  // Check if this is the last file in the directory
506  // If DirEntry[0] == 0x00 then that means all the
507  // entries after this one are unused. If this is the
508  // last entry then we didn't find the file in this directory.
509  //
510  if (DirEntry->FileName[0] == '\0')
511  {
512  return FALSE;
513  }
514 
515  //
516  // Check if this is a deleted entry or not
517  //
518  if (DirEntry->FileName[0] == '\xE5')
519  {
520  memset(ShortNameBuffer, 0, 13 * sizeof(CHAR));
521  memset(LfnNameBuffer, 0, 261 * sizeof(CHAR));
522  continue;
523  }
524 
525  //
526  // Check if this is a LFN entry
527  // If so it needs special handling
528  //
529  if (DirEntry->Attr == ATTR_LONG_NAME)
530  {
531  //
532  // Check to see if this is a deleted LFN entry, if so continue
533  //
534  if (LfnDirEntry->SequenceNumber & 0x80)
535  {
536  continue;
537  }
538 
539  //
540  // Mask off high two bits of sequence number
541  // and make the sequence number zero-based
542  //
543  LfnDirEntry->SequenceNumber &= 0x3F;
544  LfnDirEntry->SequenceNumber--;
545 
546  //
547  // Get all 13 LFN entry characters
548  //
549  if (LfnDirEntry->Name0_4[0] != 0xFFFF)
550  {
551  LfnNameBuffer[0 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[0];
552  }
553  if (LfnDirEntry->Name0_4[1] != 0xFFFF)
554  {
555  LfnNameBuffer[1 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[1];
556  }
557  if (LfnDirEntry->Name0_4[2] != 0xFFFF)
558  {
559  LfnNameBuffer[2 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[2];
560  }
561  if (LfnDirEntry->Name0_4[3] != 0xFFFF)
562  {
563  LfnNameBuffer[3 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[3];
564  }
565  if (LfnDirEntry->Name0_4[4] != 0xFFFF)
566  {
567  LfnNameBuffer[4 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name0_4[4];
568  }
569  if (LfnDirEntry->Name5_10[0] != 0xFFFF)
570  {
571  LfnNameBuffer[5 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[0];
572  }
573  if (LfnDirEntry->Name5_10[1] != 0xFFFF)
574  {
575  LfnNameBuffer[6 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[1];
576  }
577  if (LfnDirEntry->Name5_10[2] != 0xFFFF)
578  {
579  LfnNameBuffer[7 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[2];
580  }
581  if (LfnDirEntry->Name5_10[3] != 0xFFFF)
582  {
583  LfnNameBuffer[8 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[3];
584  }
585  if (LfnDirEntry->Name5_10[4] != 0xFFFF)
586  {
587  LfnNameBuffer[9 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[4];
588  }
589  if (LfnDirEntry->Name5_10[5] != 0xFFFF)
590  {
591  LfnNameBuffer[10 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name5_10[5];
592  }
593  if (LfnDirEntry->Name11_12[0] != 0xFFFF)
594  {
595  LfnNameBuffer[11 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[0];
596  }
597  if (LfnDirEntry->Name11_12[1] != 0xFFFF)
598  {
599  LfnNameBuffer[12 + (LfnDirEntry->SequenceNumber * 13)] = (UCHAR)LfnDirEntry->Name11_12[1];
600  }
601 
602  //TRACE("Dumping long name buffer:\n");
603  //DbgDumpBuffer(DPRINT_FILESYSTEM, LfnNameBuffer, 260);
604 
605  continue;
606  }
607 
608  //
609  // Check for the volume label attribute
610  // and skip over this entry if found
611  //
612  if (DirEntry->Attr & ATTR_VOLUMENAME)
613  {
614  memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
615  memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
616  continue;
617  }
618 
619  //
620  // If we get here then we've found a short file name
621  // entry and LfnNameBuffer contains the long file
622  // name or zeroes. All we have to do now is see if the
623  // file name matches either the short or long file name
624  // and fill in the FAT_FILE_INFO structure if it does
625  // or zero our buffers and continue looking.
626  //
627 
628  //
629  // Get short file name
630  //
631  FatParseShortFileName(ShortNameBuffer, DirEntry);
632 
633  //TRACE("Entry: %d LFN = %s\n", CurrentEntry, LfnNameBuffer);
634  //TRACE("Entry: %d DOS name = %s\n", CurrentEntry, ShortNameBuffer);
635 
636  //
637  // See if the file name matches either the short or long name
638  //
639  if (((strlen(FileName) == strlen(LfnNameBuffer)) && (_stricmp(FileName, LfnNameBuffer) == 0)) ||
640  ((strlen(FileName) == strlen(ShortNameBuffer)) && (_stricmp(FileName, ShortNameBuffer) == 0))) {
641  //
642  // We found the entry, now fill in the FAT_FILE_INFO struct
643  //
644  FatFileInfoPointer->Attributes = DirEntry->Attr;
645  FatFileInfoPointer->FileSize = DirEntry->Size;
646  FatFileInfoPointer->FilePointer = 0;
647 
648  TRACE("MSDOS Directory Entry:\n");
649  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]);
650  TRACE("Attr = 0x%x\n", DirEntry->Attr);
651  TRACE("ReservedNT = 0x%x\n", DirEntry->ReservedNT);
652  TRACE("TimeInTenths = %d\n", DirEntry->TimeInTenths);
653  TRACE("CreateTime = %d\n", DirEntry->CreateTime);
654  TRACE("CreateDate = %d\n", DirEntry->CreateDate);
655  TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
656  TRACE("ClusterHigh = 0x%x\n", DirEntry->ClusterHigh);
657  TRACE("Time = %d\n", DirEntry->Time);
658  TRACE("Date = %d\n", DirEntry->Date);
659  TRACE("ClusterLow = 0x%x\n", DirEntry->ClusterLow);
660  TRACE("Size = %d\n", DirEntry->Size);
661 
662  //
663  // Get the cluster chain
664  //
665  StartCluster = ((ULONG)DirEntry->ClusterHigh << 16) + DirEntry->ClusterLow;
666  TRACE("StartCluster = 0x%x\n", StartCluster);
667  FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume, StartCluster);
668 
669  //
670  // See if memory allocation failed
671  //
672  if (FatFileInfoPointer->FileFatChain == NULL)
673  {
674  return FALSE;
675  }
676 
677  return TRUE;
678  }
679 
680  //
681  // Nope, no match - zero buffers and continue looking
682  //
683  memset(ShortNameBuffer, 0, 13 * sizeof(UCHAR));
684  memset(LfnNameBuffer, 0, 261 * sizeof(UCHAR));
685  continue;
686  }
687 
688  return FALSE;
689 }
690 
691 static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
692 {
693  ULONG EntryCount;
694  ULONG CurrentEntry;
696  FATX_DIRENTRY OurDirEntry;
697  PFATX_DIRENTRY DirEntry = &OurDirEntry;
698 
699  EntryCount = DirectorySize / sizeof(FATX_DIRENTRY);
700 
701  TRACE("FatXSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName);
702 
704 
705  for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++, DirectoryBuffer = ((PFATX_DIRENTRY)DirectoryBuffer)+1)
706  {
707  OurDirEntry = *(PFATX_DIRENTRY) DirectoryBuffer;
708  FatSwapFatXDirEntry(&OurDirEntry);
709  if (0xff == DirEntry->FileNameSize)
710  {
711  break;
712  }
713  if (0xe5 == DirEntry->FileNameSize)
714  {
715  continue;
716  }
717  if (FileNameLen == DirEntry->FileNameSize &&
718  0 == _strnicmp(FileName, DirEntry->FileName, FileNameLen))
719  {
720  /*
721  * We found the entry, now fill in the FAT_FILE_INFO struct
722  */
723  FatFileInfoPointer->FileSize = DirEntry->Size;
724  FatFileInfoPointer->FilePointer = 0;
725 
726  TRACE("FATX Directory Entry:\n");
727  TRACE("FileNameSize = %d\n", DirEntry->FileNameSize);
728  TRACE("Attr = 0x%x\n", DirEntry->Attr);
729  TRACE("StartCluster = 0x%x\n", DirEntry->StartCluster);
730  TRACE("Size = %d\n", DirEntry->Size);
731  TRACE("Time = %d\n", DirEntry->Time);
732  TRACE("Date = %d\n", DirEntry->Date);
733  TRACE("CreateTime = %d\n", DirEntry->CreateTime);
734  TRACE("CreateDate = %d\n", DirEntry->CreateDate);
735  TRACE("LastAccessTime = %d\n", DirEntry->LastAccessTime);
736  TRACE("LastAccessDate = %d\n", DirEntry->LastAccessDate);
737 
738  /*
739  * Get the cluster chain
740  */
741  FatFileInfoPointer->FileFatChain = FatGetClusterChainArray(Volume, DirEntry->StartCluster);
742 
743  /*
744  * See if memory allocation failed
745  */
746  if (NULL == FatFileInfoPointer->FileFatChain)
747  {
748  return FALSE;
749  }
750 
751  return TRUE;
752  }
753  }
754 
755  return FALSE;
756 }
757 
758 /*
759  * FatLookupFile()
760  * This function searches the file system for the
761  * specified filename and fills in an FAT_FILE_INFO structure
762  * with info describing the file, etc. returns ARC error code
763  */
765 {
766  UINT32 i;
767  ULONG NumberOfPathParts;
768  CHAR PathPart[261];
769  PVOID DirectoryBuffer;
770  ULONG DirectoryStartCluster = 0;
771  ULONG DirectorySize;
772  FAT_FILE_INFO FatFileInfo;
773 
774  TRACE("FatLookupFile() FileName = %s\n", FileName);
775 
776  memset(FatFileInfoPointer, 0, sizeof(FAT_FILE_INFO));
777 
778  //
779  // Figure out how many sub-directories we are nested in
780  //
781  NumberOfPathParts = FsGetNumPathParts(FileName);
782 
783  //
784  // Loop once for each part
785  //
786  for (i=0; i<NumberOfPathParts; i++)
787  {
788  //
789  // Get first path part
790  //
791  FsGetFirstNameFromPath(PathPart, FileName);
792 
793  //
794  // Advance to the next part of the path
795  //
796  for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
797  {
798  }
799  FileName++;
800 
801  //
802  // Buffer the directory contents
803  //
804  DirectoryBuffer = FatBufferDirectory(Volume, DirectoryStartCluster, &DirectorySize, (i == 0) );
805  if (DirectoryBuffer == NULL)
806  {
807  return ENOMEM;
808  }
809 
810  //
811  // Search for file name in directory
812  //
813  if (ISFATX(Volume->FatType))
814  {
815  if (!FatXSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
816  {
817  return ENOENT;
818  }
819  }
820  else
821  {
822  if (!FatSearchDirectoryBufferForFile(Volume, DirectoryBuffer, DirectorySize, PathPart, &FatFileInfo))
823  {
824  return ENOENT;
825  }
826  }
827 
828  //
829  // If we have another sub-directory to go then
830  // grab the start cluster and free the fat chain array
831  //
832  if ((i+1) < NumberOfPathParts)
833  {
834  //
835  // Check if current entry is a directory
836  //
837  if (!(FatFileInfo.Attributes & ATTR_DIRECTORY))
838  {
840  return ENOTDIR;
841  }
842  DirectoryStartCluster = FatFileInfo.FileFatChain[0];
844  FatFileInfo.FileFatChain = NULL;
845  }
846  }
847 
848  memcpy(FatFileInfoPointer, &FatFileInfo, sizeof(FAT_FILE_INFO));
849 
850  return ESUCCESS;
851 }
852 
853 /*
854  * FatParseFileName()
855  * This function parses a directory entry name which
856  * is in the form of "FILE EXT" and puts it in Buffer
857  * in the form of "file.ext"
858  */
860 {
861  ULONG Idx;
862 
863  Idx = 0;
864  RtlZeroMemory(Buffer, 13);
865 
866  //
867  // Fixup first character
868  //
869  if (DirEntry->FileName[0] == 0x05)
870  {
871  DirEntry->FileName[0] = 0xE5;
872  }
873 
874  //
875  // Get the file name
876  //
877  while (Idx < 8)
878  {
879  if (DirEntry->FileName[Idx] == ' ')
880  {
881  break;
882  }
883 
884  Buffer[Idx] = DirEntry->FileName[Idx];
885  Idx++;
886  }
887 
888  //
889  // Get extension
890  //
891  if ((DirEntry->FileName[8] != ' '))
892  {
893  Buffer[Idx++] = '.';
894  Buffer[Idx++] = (DirEntry->FileName[8] == ' ') ? '\0' : DirEntry->FileName[8];
895  Buffer[Idx++] = (DirEntry->FileName[9] == ' ') ? '\0' : DirEntry->FileName[9];
896  Buffer[Idx++] = (DirEntry->FileName[10] == ' ') ? '\0' : DirEntry->FileName[10];
897  }
898 
899  //TRACE("FatParseShortFileName() ShortName = %s\n", Buffer);
900 }
901 
902 /*
903  * FatGetFatEntry()
904  * returns the Fat entry for a given cluster number
905  */
907 {
908  ULONG fat = 0;
909  UINT32 FatOffset;
910  UINT32 ThisFatSecNum;
911  UINT32 ThisFatEntOffset;
914  BOOLEAN Success = TRUE;
915 
916  //TRACE("FatGetFatEntry() Retrieving FAT entry for cluster %d.\n", Cluster);
917 
918  // We need a buffer for 2 sectors
919  ReadBuffer = FrLdrTempAlloc(2 * Volume->BytesPerSector, TAG_FAT_BUFFER);
920  if (!ReadBuffer)
921  {
922  return FALSE;
923  }
924 
925  switch(Volume->FatType)
926  {
927  case FAT12:
928 
929  FatOffset = Cluster + (Cluster / 2);
930  ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
931  ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
932 
933  TRACE("FatOffset: %d\n", FatOffset);
934  TRACE("ThisFatSecNum: %d\n", ThisFatSecNum);
935  TRACE("ThisFatEntOffset: %d\n", ThisFatEntOffset);
936 
937  if (ThisFatEntOffset == (Volume->BytesPerSector - 1))
938  {
939  SectorCount = 2;
940  }
941  else
942  {
943  SectorCount = 1;
944  }
945 
946  if (!FatReadVolumeSectors(Volume, ThisFatSecNum, SectorCount, ReadBuffer))
947  {
948  Success = FALSE;
949  break;
950  }
951 
952  fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
953  fat = SWAPW(fat);
954  if (Cluster & 0x0001)
955  fat = fat >> 4; /* Cluster number is ODD */
956  else
957  fat = fat & 0x0FFF; /* Cluster number is EVEN */
958 
959  break;
960 
961  case FAT16:
962  case FATX16:
963 
964  FatOffset = (Cluster * 2);
965  ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
966  ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
967 
968  if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, ReadBuffer))
969  {
970  Success = FALSE;
971  break;
972  }
973 
974  fat = *((USHORT *) (ReadBuffer + ThisFatEntOffset));
975  fat = SWAPW(fat);
976 
977  break;
978 
979  case FAT32:
980  case FATX32:
981 
982  FatOffset = (Cluster * 4);
983  ThisFatSecNum = Volume->ActiveFatSectorStart + (FatOffset / Volume->BytesPerSector);
984  ThisFatEntOffset = (FatOffset % Volume->BytesPerSector);
985 
986  if (!FatReadVolumeSectors(Volume, ThisFatSecNum, 1, ReadBuffer))
987  {
988  return FALSE;
989  }
990 
991  // Get the fat entry
992  fat = (*((ULONG *) (ReadBuffer + ThisFatEntOffset))) & 0x0FFFFFFF;
993  fat = SWAPD(fat);
994 
995  break;
996 
997  default:
998  ERR("Unknown FAT type %d\n", Volume->FatType);
999  Success = FALSE;
1000  break;
1001  }
1002 
1003  //TRACE("FAT entry is 0x%x.\n", fat);
1004 
1006 
1007  *ClusterPointer = fat;
1008 
1009  return Success;
1010 }
1011 
1013 {
1014  ULONG ClusterCount = 0;
1015 
1016  TRACE("FatCountClustersInChain() StartCluster = %d\n", StartCluster);
1017 
1018  while (1)
1019  {
1020  //
1021  // If end of chain then break out of our cluster counting loop
1022  //
1023  if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
1024  ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartCluster >= 0xfff8)) ||
1025  ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
1026  {
1027  break;
1028  }
1029 
1030  //
1031  // Increment count
1032  //
1033  ClusterCount++;
1034 
1035  //
1036  // Get next cluster
1037  //
1038  if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
1039  {
1040  return 0;
1041  }
1042  }
1043 
1044  TRACE("FatCountClustersInChain() ClusterCount = %d\n", ClusterCount);
1045 
1046  return ClusterCount;
1047 }
1048 
1050 {
1051  ULONG ClusterCount;
1052  ULONG ArraySize;
1053  ULONG* ArrayPointer;
1054  ULONG Idx;
1055 
1056  TRACE("FatGetClusterChainArray() StartCluster = %d\n", StartCluster);
1057 
1058  ClusterCount = FatCountClustersInChain(Volume, StartCluster) + 1; // Lets get the 0x0ffffff8 on the end of the array
1059  ArraySize = ClusterCount * sizeof(ULONG);
1060 
1061  //
1062  // Allocate array memory
1063  //
1064  ArrayPointer = FrLdrTempAlloc(ArraySize, TAG_FAT_CHAIN);
1065 
1066  if (ArrayPointer == NULL)
1067  {
1068  return NULL;
1069  }
1070 
1071  //
1072  // Loop through and set array values
1073  //
1074  for (Idx=0; Idx<ClusterCount; Idx++)
1075  {
1076  //
1077  // Set current cluster
1078  //
1079  ArrayPointer[Idx] = StartCluster;
1080 
1081  //
1082  // Don't try to get next cluster for last cluster
1083  //
1084  if (((Volume->FatType == FAT12) && (StartCluster >= 0xff8)) ||
1085  ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartCluster >= 0xfff8)) ||
1086  ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartCluster >= 0x0ffffff8)))
1087  {
1088  Idx++;
1089  break;
1090  }
1091 
1092  //
1093  // Get next cluster
1094  //
1095  if (!FatGetFatEntry(Volume, StartCluster, &StartCluster))
1096  {
1097  FrLdrTempFree(ArrayPointer, TAG_FAT_CHAIN);
1098  return NULL;
1099  }
1100  }
1101 
1102  return ArrayPointer;
1103 }
1104 
1105 /*
1106  * FatReadClusterChain()
1107  * Reads the specified clusters into memory
1108  */
1110 {
1111  ULONG ClusterStartSector;
1112 
1113  TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
1114 
1115  while (NumberOfClusters > 0)
1116  {
1117 
1118  //TRACE("FatReadClusterChain() StartClusterNumber = %d NumberOfClusters = %d Buffer = 0x%x\n", StartClusterNumber, NumberOfClusters, Buffer);
1119  //
1120  // Calculate starting sector for cluster
1121  //
1122  ClusterStartSector = ((StartClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
1123 
1124  //
1125  // Read cluster into memory
1126  //
1127  if (!FatReadVolumeSectors(Volume, ClusterStartSector, Volume->SectorsPerCluster, Buffer))
1128  {
1129  return FALSE;
1130  }
1131 
1132  //
1133  // Decrement count of clusters left to read
1134  //
1135  NumberOfClusters--;
1136 
1137  //
1138  // Increment buffer address by cluster size
1139  //
1140  Buffer = (PVOID)((ULONG_PTR)Buffer + (Volume->SectorsPerCluster * Volume->BytesPerSector));
1141 
1142  //
1143  // Get next cluster
1144  //
1145  if (!FatGetFatEntry(Volume, StartClusterNumber, &StartClusterNumber))
1146  {
1147  return FALSE;
1148  }
1149 
1150  //
1151  // If end of chain then break out of our cluster reading loop
1152  //
1153  if (((Volume->FatType == FAT12) && (StartClusterNumber >= 0xff8)) ||
1154  ((Volume->FatType == FAT16 || Volume->FatType == FATX16) && (StartClusterNumber >= 0xfff8)) ||
1155  ((Volume->FatType == FAT32 || Volume->FatType == FATX32) && (StartClusterNumber >= 0x0ffffff8)))
1156  {
1157  break;
1158  }
1159  }
1160 
1161  return TRUE;
1162 }
1163 
1164 /*
1165  * FatReadPartialCluster()
1166  * Reads part of a cluster into memory
1167  */
1169 {
1170  ULONG ClusterStartSector;
1171  ULONG SectorOffset, ReadSize, SectorCount;
1173  BOOLEAN Success = FALSE;
1174 
1175  //TRACE("FatReadPartialCluster() ClusterNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", ClusterNumber, StartingOffset, Length, Buffer);
1176 
1177  ClusterStartSector = ((ClusterNumber - 2) * Volume->SectorsPerCluster) + Volume->DataSectorStart;
1178 
1179  // This is the offset of the data in sectors
1180  SectorOffset = (StartingOffset / Volume->BytesPerSector);
1181  StartingOffset %= Volume->BytesPerSector;
1182 
1183  // Calculate how many sectors we need to read
1184  SectorCount = (StartingOffset + Length + Volume->BytesPerSector - 1) / Volume->BytesPerSector;
1185 
1186  // Calculate rounded up read size
1187  ReadSize = SectorCount * Volume->BytesPerSector;
1188 
1190  if (!ReadBuffer)
1191  {
1192  return FALSE;
1193  }
1194 
1195  if (FatReadVolumeSectors(Volume, ClusterStartSector + SectorOffset, SectorCount, ReadBuffer))
1196  {
1198  Success = TRUE;
1199  }
1200 
1202 
1203  return Success;
1204 }
1205 
1206 /*
1207  * FatReadFile()
1208  * Reads BytesToRead from open file and
1209  * returns the number of bytes read in BytesRead
1210  */
1212 {
1213  PFAT_VOLUME_INFO Volume = FatFileInfo->Volume;
1214  ULONG ClusterNumber;
1215  ULONG OffsetInCluster;
1216  ULONG LengthInCluster;
1217  ULONG NumberOfClusters;
1218  ULONG BytesPerCluster;
1219 
1220  TRACE("FatReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer);
1221 
1222  if (BytesRead != NULL)
1223  {
1224  *BytesRead = 0;
1225  }
1226 
1227  //
1228  // If they are trying to read past the
1229  // end of the file then return success
1230  // with BytesRead == 0
1231  //
1232  if (FatFileInfo->FilePointer >= FatFileInfo->FileSize)
1233  {
1234  return TRUE;
1235  }
1236 
1237  //
1238  // If they are trying to read more than there is to read
1239  // then adjust the amount to read
1240  //
1241  if ((FatFileInfo->FilePointer + BytesToRead) > FatFileInfo->FileSize)
1242  {
1243  BytesToRead = (FatFileInfo->FileSize - FatFileInfo->FilePointer);
1244  }
1245 
1246  //
1247  // Ok, now we have to perform at most 3 calculations
1248  // I'll draw you a picture (using nifty ASCII art):
1249  //
1250  // CurrentFilePointer -+
1251  // |
1252  // +----------------+
1253  // |
1254  // +-----------+-----------+-----------+-----------+
1255  // | Cluster 1 | Cluster 2 | Cluster 3 | Cluster 4 |
1256  // +-----------+-----------+-----------+-----------+
1257  // | |
1258  // +---------------+--------------------+
1259  // |
1260  // BytesToRead -------+
1261  //
1262  // 1 - The first calculation (and read) will align
1263  // the file pointer with the next cluster.
1264  // boundary (if we are supposed to read that much)
1265  // 2 - The next calculation (and read) will read
1266  // in all the full clusters that the requested
1267  // amount of data would cover (in this case
1268  // clusters 2 & 3).
1269  // 3 - The last calculation (and read) would read
1270  // in the remainder of the data requested out of
1271  // the last cluster.
1272  //
1273 
1274  BytesPerCluster = Volume->SectorsPerCluster * Volume->BytesPerSector;
1275 
1276  //
1277  // Only do the first read if we
1278  // aren't aligned on a cluster boundary
1279  //
1280  if (FatFileInfo->FilePointer % BytesPerCluster)
1281  {
1282  //
1283  // Do the math for our first read
1284  //
1285  ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
1286  ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
1287  OffsetInCluster = (FatFileInfo->FilePointer % BytesPerCluster);
1288  LengthInCluster = (BytesToRead > (BytesPerCluster - OffsetInCluster)) ? (BytesPerCluster - OffsetInCluster) : BytesToRead;
1289 
1290  //
1291  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
1292  //
1293  if (!FatReadPartialCluster(Volume, ClusterNumber, OffsetInCluster, LengthInCluster, Buffer))
1294  {
1295  return FALSE;
1296  }
1297  if (BytesRead != NULL)
1298  {
1299  *BytesRead += LengthInCluster;
1300  }
1301  BytesToRead -= LengthInCluster;
1302  FatFileInfo->FilePointer += LengthInCluster;
1303  Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInCluster);
1304  }
1305 
1306  //
1307  // Do the math for our second read (if any data left)
1308  //
1309  if (BytesToRead > 0)
1310  {
1311  //
1312  // Determine how many full clusters we need to read
1313  //
1314  NumberOfClusters = (BytesToRead / BytesPerCluster);
1315 
1316  if (NumberOfClusters > 0)
1317  {
1318  ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
1319  ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
1320 
1321  //
1322  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
1323  //
1324  if (!FatReadClusterChain(Volume, ClusterNumber, NumberOfClusters, Buffer))
1325  {
1326  return FALSE;
1327  }
1328  if (BytesRead != NULL)
1329  {
1330  *BytesRead += (NumberOfClusters * BytesPerCluster);
1331  }
1332  BytesToRead -= (NumberOfClusters * BytesPerCluster);
1333  FatFileInfo->FilePointer += (NumberOfClusters * BytesPerCluster);
1334  Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfClusters * BytesPerCluster));
1335  }
1336  }
1337 
1338  //
1339  // Do the math for our third read (if any data left)
1340  //
1341  if (BytesToRead > 0)
1342  {
1343  ClusterNumber = (FatFileInfo->FilePointer / BytesPerCluster);
1344  ClusterNumber = FatFileInfo->FileFatChain[ClusterNumber];
1345 
1346  //
1347  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
1348  //
1349  if (!FatReadPartialCluster(Volume, ClusterNumber, 0, BytesToRead, Buffer))
1350  {
1351  return FALSE;
1352  }
1353  if (BytesRead != NULL)
1354  {
1355  *BytesRead += BytesToRead;
1356  }
1357  FatFileInfo->FilePointer += BytesToRead;
1358  BytesToRead -= BytesToRead;
1359  Buffer = (PVOID)((ULONG_PTR)Buffer + BytesToRead);
1360  }
1361 
1362  return TRUE;
1363 }
1364 
1366 {
1368  ULONG Count;
1370 
1371  //TRACE("FatReadVolumeSectors(): SectorNumber %d, SectorCount %d, Buffer %p\n",
1372  // SectorNumber, SectorCount, Buffer);
1373 
1374  //
1375  // Seek to right position
1376  //
1377  Position.QuadPart = (ULONGLONG)SectorNumber * 512;
1378  Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
1379  if (Status != ESUCCESS)
1380  {
1381  TRACE("FatReadVolumeSectors() Failed to seek\n");
1382  return FALSE;
1383  }
1384 
1385  //
1386  // Read data
1387  //
1388  Status = ArcRead(Volume->DeviceId, Buffer, SectorCount * 512, &Count);
1389  if (Status != ESUCCESS || Count != SectorCount * 512)
1390  {
1391  TRACE("FatReadVolumeSectors() Failed to read\n");
1392  return FALSE;
1393  }
1394 
1395  // Return success
1396  return TRUE;
1397 }
1398 
1400 {
1402 
1403  if (FileHandle->FileFatChain) FrLdrTempFree(FileHandle->FileFatChain, TAG_FAT_CHAIN);
1405 
1406  return ESUCCESS;
1407 }
1408 
1410 {
1412 
1414  Information->EndingAddress.LowPart = FileHandle->FileSize;
1415  Information->CurrentAddress.LowPart = FileHandle->FilePointer;
1416 
1417  TRACE("FatGetFileInformation() FileSize = %d\n",
1418  Information->EndingAddress.LowPart);
1419  TRACE("FatGetFileInformation() FilePointer = %d\n",
1420  Information->CurrentAddress.LowPart);
1421 
1422  return ESUCCESS;
1423 }
1424 
1426 {
1427  PFAT_VOLUME_INFO FatVolume;
1428  FAT_FILE_INFO TempFileInfo;
1430  ULONG DeviceId;
1433 
1434  if (OpenMode != OpenReadOnly && OpenMode != OpenDirectory)
1435  return EACCES;
1436 
1437  DeviceId = FsGetDeviceId(*FileId);
1438  FatVolume = FatVolumes[DeviceId];
1439 
1440  TRACE("FatOpen() FileName = %s\n", Path);
1441 
1442  RtlZeroMemory(&TempFileInfo, sizeof(TempFileInfo));
1443  Status = FatLookupFile(FatVolume, Path, DeviceId, &TempFileInfo);
1444  if (Status != ESUCCESS)
1445  return ENOENT;
1446 
1447  //
1448  // Check if caller opened what he expected (dir vs file)
1449  //
1450  IsDirectory = (TempFileInfo.Attributes & ATTR_DIRECTORY) != 0;
1451  if (IsDirectory && OpenMode != OpenDirectory)
1452  return EISDIR;
1453  else if (!IsDirectory && OpenMode != OpenReadOnly)
1454  return ENOTDIR;
1455 
1457  if (!FileHandle)
1458  return ENOMEM;
1459 
1460  RtlCopyMemory(FileHandle, &TempFileInfo, sizeof(FAT_FILE_INFO));
1461  FileHandle->Volume = FatVolume;
1462 
1463  FsSetDeviceSpecific(*FileId, FileHandle);
1464  return ESUCCESS;
1465 }
1466 
1468 {
1470  BOOLEAN Success;
1471 
1472  //
1473  // Call old read method
1474  //
1476 
1477  //
1478  // Check for success
1479  //
1480  if (Success)
1481  return ESUCCESS;
1482  else
1483  return EIO;
1484 }
1485 
1487 {
1489 
1490  TRACE("FatSeek() NewFilePointer = %lu\n", Position->LowPart);
1491 
1492  if (SeekMode != SeekAbsolute)
1493  return EINVAL;
1494  if (Position->HighPart != 0)
1495  return EINVAL;
1496  if (Position->LowPart >= FileHandle->FileSize)
1497  return EINVAL;
1498 
1499  FileHandle->FilePointer = Position->LowPart;
1500  return ESUCCESS;
1501 }
1502 
1504 {
1505  FatClose,
1507  FatOpen,
1508  FatRead,
1509  FatSeek,
1510  L"fastfat",
1511 };
1512 
1513 const DEVVTBL* FatMount(ULONG DeviceId)
1514 {
1516  UCHAR Buffer[512];
1519  PFATX_BOOTSECTOR BootSectorX = (PFATX_BOOTSECTOR)Buffer;
1522  ULONG Count;
1525 
1526  //
1527  // Allocate data for volume information
1528  //
1530  if (!Volume)
1531  return NULL;
1533 
1534  //
1535  // Read the BootSector
1536  //
1537  Position.HighPart = 0;
1538  Position.LowPart = 0;
1539  Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1540  if (Status != ESUCCESS)
1541  {
1543  return NULL;
1544  }
1545  Status = ArcRead(DeviceId, Buffer, sizeof(Buffer), &Count);
1546  if (Status != ESUCCESS || Count != sizeof(Buffer))
1547  {
1549  return NULL;
1550  }
1551 
1552  //
1553  // Check if BootSector is valid. If no, return early
1554  //
1555  if (!RtlEqualMemory(BootSector->FileSystemType, "FAT12 ", 8) &&
1556  !RtlEqualMemory(BootSector->FileSystemType, "FAT16 ", 8) &&
1557  !RtlEqualMemory(BootSector32->FileSystemType, "FAT32 ", 8) &&
1558  !RtlEqualMemory(BootSectorX->FileSystemType, "FATX", 4))
1559  {
1561  return NULL;
1562  }
1563 
1564  //
1565  // Determine sector count
1566  //
1568  if (Status != ESUCCESS)
1569  {
1571  return NULL;
1572  }
1573  SectorCount.HighPart = FileInformation.EndingAddress.HighPart;
1574  SectorCount.LowPart = FileInformation.EndingAddress.LowPart;
1575  SectorCount.QuadPart /= SECTOR_SIZE;
1576 
1577  //
1578  // Keep device id
1579  //
1580  Volume->DeviceId = DeviceId;
1581 
1582  //
1583  // Really open the volume
1584  //
1585  if (!FatOpenVolume(Volume, BootSector, SectorCount.QuadPart))
1586  {
1588  return NULL;
1589  }
1590 
1591  //
1592  // Remember FAT volume information
1593  //
1594  FatVolumes[DeviceId] = Volume;
1595 
1596  //
1597  // Return success
1598  //
1599  return &FatFuncTable;
1600 }
USHORT BytesPerSector
Definition: bootsup.c:79
UCHAR SectorsPerCluster
Definition: bootsup.c:51
ULONG PartitionSectorCount
Definition: xboxdisk.c:39
signed char * PCHAR
Definition: retypes.h:7
#define FAT12
Definition: fat.h:167
ULONG SectorsPerCluster
Definition: fat.c:47
#define SD(Object, Field)
Definition: bytesex.h:10
struct DIRENTRY * PDIRENTRY
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
PVOID FatBufferDirectory(PFAT_VOLUME_INFO Volume, ULONG DirectoryStartCluster, ULONG *EntryCountPointer, BOOLEAN RootDirectory)
Definition: fat.c:388
VOID FatSwapFatXBootSector(PFATX_BOOTSECTOR Obj)
Definition: fat.c:97
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:414
#define SWAPW(x)
Definition: bytesex.h:8
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
UCHAR SectorsPerCluster
Definition: bootsup.c:80
UCHAR SequenceNumber
Definition: fat.h:120
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
USHORT TotalSectors
Definition: bootsup.c:55
struct _Entry Entry
Definition: kefuncs.h:640
VOID FatSwapDirEntry(PDIRENTRY Obj)
Definition: fat.c:104
UCHAR Reserved1
Definition: bootsup.c:99
ULONG FatSectorStart
Definition: fat.c:48
#define TAG_FAT_BUFFER
Definition: fat.c:42
Definition: arc.h:32
NTSTATUS FatMount(_In_ ULONG DeviceId, _In_ ULONG Unknown, _Out_ PBL_FILE_ENTRY *FileEntry)
Definition: fat.c:23
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
USHORT BootSectorMagic
Definition: bootsup.c:107
static BOOLEAN FatXSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:691
Definition: arc.h:39
static COORD Position
Definition: mouse.c:34
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
#define ReadBuffer(BaseIoAddress, Buffer, Count)
Definition: atapi.h:339
UCHAR JumpBoot[3]
Definition: bootsup.c:77
Definition: fs.h:22
PFAT_VOLUME_INFO Volume
Definition: fat.h:155
#define ISFATX(FT)
Definition: fat.h:173
VOID FatSwapFatXDirEntry(PFATX_DIRENTRY Obj)
Definition: fat.c:128
#define SWAPD(x)
Definition: bytesex.h:7
struct _FAT_VOLUME_INFO FAT_VOLUME_INFO
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:386
static OUT PIO_STATUS_BLOCK OUT PVOID FileInformation
Definition: pipe.c:75
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG TotalSectorsBig
Definition: bootsup.c:90
#define SW(Object, Field)
Definition: bytesex.h:11
ULONG ARC_STATUS
Definition: arc.h:4
ULONG * FileFatChain
Definition: fat.h:153
_In_ ULONG _In_ ULONG _In_ ULONG NumberOfHeads
Definition: iofuncs.h:2066
#define InsertTailList(ListHead, Entry)
struct FATX_DIRENTRY * PFATX_DIRENTRY
#define ATTR_LONG_NAME
Definition: fat.h:165
#define _stricmp
Definition: cat.c:22
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:474
Definition: arc.h:48
static int Link(const char **args)
Definition: vfdcmd.c:2414
PVOID Volume
Definition: fat.c:380
LIST_ENTRY Link
Definition: fat.c:379
BOOL BackupBootSector(LPCTSTR lpszVolumeName)
Definition: install.c:61
ULONG VolumeSerialNumber
Definition: bootsup.c:101
BOOLEAN FatReadClusterChain(PFAT_VOLUME_INFO Volume, ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer)
Definition: fat.c:1109
DBG_DEFAULT_CHANNEL(FILESYSTEM)
uint32_t ULONG_PTR
Definition: typedefs.h:63
USHORT BytesPerSector
Definition: bootsup.c:50
CHAR VolumeLabel[11]
Definition: bootsup.c:66
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define ATTR_VOLUMENAME
Definition: fat.h:162
HANDLE FileHandle
Definition: stats.c:38
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
ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONGLONG PartitionSectorCount)
Definition: fat.c:322
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2066
struct LFN_DIRENTRY * PLFN_DIRENTRY
unsigned int UINT32
#define SECTOR_SIZE
Definition: winldr.h:34
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:260
#define FATX32
Definition: fat.h:171
struct _FAT32_BOOTSECTOR * PFAT32_BOOTSECTOR
ULONG SectorsPerFatBig
Definition: bootsup.c:91
Definition: bidi.c:97
USHORT RootDirEntries
Definition: bootsup.c:54
ULONG DirectorySize
Definition: fat.c:382
struct _DIRECTORY_BUFFER * PDIRECTORY_BUFFER
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
CHAR OemName[8]
Definition: bootsup.c:49
UCHAR JumpBoot[3]
Definition: bootsup.c:48
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
ULONG FatType
Definition: fat.c:56
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
ULONG FilePointer
Definition: fat.h:152
smooth NULL
Definition: ftsmooth.c:416
ARC_STATUS FatGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fat.c:1409
USHORT NumberOfHeads
Definition: bootsup.c:59
struct tagDIRENTRY DIRENTRY
enum _SEEKMODE SEEKMODE
Definition: bufpool.h:45
USHORT NumberOfFats
Definition: fat.h:93
void * PVOID
Definition: retypes.h:9
WCHAR Name5_10[6]
Definition: fat.h:125
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
ULONG DirectoryStartCluster
Definition: fat.c:381
ULONG SectorsPerFat
Definition: fat.c:51
CHAR FileSystemType[8]
Definition: bootsup.c:103
UCHAR BootSignature
Definition: bootsup.c:64
Definition: arc.h:50
USHORT RootDirEntries
Definition: bootsup.c:83
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID FatSwapFatBootSector(PFAT_BOOTSECTOR Obj)
Definition: fat.c:62
#define TRACE(s)
Definition: solgame.cpp:4
Dirent FileNameLen
Definition: dirsup.c:506
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
USHORT ReservedSectors
Definition: bootsup.c:52
USHORT ReservedSectors
Definition: bootsup.c:81
PFAT_VOLUME_INFO FatVolumes[MAX_FDS]
Definition: fat.c:60
CHAR OemName[8]
Definition: bootsup.c:78
uint64_t ULONGLONG
Definition: typedefs.h:65
WCHAR Name0_4[5]
Definition: fat.h:121
#define TAG_FAT_VOLUME
Definition: fat.c:41
#define TAG_FAT_CHAIN
Definition: fat.c:39
UCHAR Reserved1
Definition: bootsup.c:63
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
USHORT SectorsPerFat
Definition: bootsup.c:57
VOID FsSetDeviceSpecific(ULONG FileId, VOID *Specific)
Definition: fs.c:467
ARC_STATUS FatRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fat.c:1467
UCHAR BootSignature
Definition: bootsup.c:100
USHORT BackupBootSector
Definition: bootsup.c:96
BOOLEAN FatReadVolumeSectors(PFAT_VOLUME_INFO Volume, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: fat.c:1365
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
USHORT BootSectorMagic
Definition: bootsup.c:71
#define MAX_FDS
Definition: fs.h:62
UCHAR NumberOfFats
Definition: bootsup.c:53
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:237
CHAR VolumeLabel[11]
Definition: bootsup.c:102
struct _FAT_BOOTSECTOR * PFAT_BOOTSECTOR
UCHAR DriveNumber
Definition: bootsup.c:98
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONG DeviceId
Definition: fat.c:57
Definition: arc.h:34
BOOLEAN FatReadFile(PFAT_FILE_INFO FatFileInfo, ULONG BytesToRead, ULONG *BytesRead, PVOID Buffer)
Definition: fat.c:1211
static const WCHAR L[]
Definition: oid.c:1250
void FatParseShortFileName(PCHAR Buffer, PDIRENTRY DirEntry)
Definition: fat.c:859
_Must_inspect_result_ _In_ PFLT_INSTANCE _Out_ PBOOLEAN IsDirectory
Definition: fltkernel.h:1139
USHORT TotalSectors
Definition: bootsup.c:84
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:244
const DEVVTBL FatFuncTable
Definition: fat.c:1503
ULONG * FatGetClusterChainArray(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
Definition: fat.c:1049
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
USHORT SectorsPerTrack
Definition: bootsup.c:87
ULONG VolumeSerialNumber
Definition: bootsup.c:65
ULONG Unknown
Definition: fat.h:94
Definition: fat.h:102
Definition: typedefs.h:117
ARC_STATUS FatOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: fat.c:1425
UCHAR MediaDescriptor
Definition: bootsup.c:85
#define ATTR_DIRECTORY
Definition: fat.h:163
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
UCHAR Data[]
Definition: fat.c:383
ULONG SectorCount
Definition: part_xbox.c:32
BOOLEAN FatOpenVolume(PFAT_VOLUME_INFO Volume, PFAT_BOOTSECTOR BootSector, ULONGLONG PartitionSectorCount)
Definition: fat.c:140
USHORT SectorsPerTrack
Definition: bootsup.c:58
#define FAT16
Definition: fat.h:168
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
USHORT FileSystemVersion
Definition: bootsup.c:93
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define TAG_FAT_FILE
Definition: fat.c:40
USHORT FsInfo
Definition: bootsup.c:95
VOID FatSwapFat32BootSector(PFAT32_BOOTSECTOR Obj)
Definition: fat.c:77
PRTL_UNICODE_STRING_BUFFER Path
ULONG NumberOfFats
Definition: fat.c:50
ULONG RootDirSectors
Definition: fat.c:53
ULONG FileSize
Definition: fat.h:151
unsigned short USHORT
Definition: pedump.c:61
ULONG RootDirStartCluster
Definition: fat.c:54
UCHAR MediaDescriptor
Definition: bootsup.c:56
ULONG BytesPerSector
Definition: fat.c:46
CHAR FileSystemType[8]
Definition: bootsup.c:67
ULONG VolumeSerialNumber
Definition: fat.h:91
ARC_STATUS FatLookupFile(PFAT_VOLUME_INFO Volume, PCSTR FileName, ULONG DeviceId, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:764
USHORT SectorsPerFat
Definition: bootsup.c:86
UCHAR NumberOfFats
Definition: bootsup.c:82
ULONG SectorsPerCluster
Definition: fat.h:92
#define FATX16
Definition: fat.h:170
Definition: arc.h:46
ULONG ActiveFatSectorStart
Definition: fat.c:49
BOOLEAN FatReadPartialCluster(PFAT_VOLUME_INFO Volume, ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
Definition: fat.c:1168
Definition: arc.h:40
Definition: arc.h:41
BOOLEAN FatGetFatEntry(PFAT_VOLUME_INFO Volume, ULONG Cluster, ULONG *ClusterPointer)
Definition: fat.c:906
#define FAT32
Definition: fat.h:169
VOID FatSwapLFNDirEntry(PLFN_DIRENTRY Obj)
Definition: fat.c:116
WCHAR Name11_12[2]
Definition: fat.h:127
USHORT NumberOfHeads
Definition: bootsup.c:88
ARC_STATUS FatSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fat.c:1486
ULONG TotalSectorsBig
Definition: bootsup.c:61
ULONG HiddenSectors
Definition: bootsup.c:60
ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: fs.c:251
ULONG HiddenSectors
Definition: bootsup.c:89
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:481
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
struct _DIRECTORY_BUFFER DIRECTORY_BUFFER
ARC_STATUS FatClose(ULONG FileId)
Definition: fat.c:1399
UCHAR Reserved[12]
Definition: bootsup.c:97
const char * PCSTR
Definition: typedefs.h:51
CHAR FileSystemType[4]
Definition: fat.h:90
ULONG RootDirSectorStart
Definition: fat.c:52
ULONG FatCountClustersInChain(PFAT_VOLUME_INFO Volume, ULONG StartCluster)
Definition: fat.c:1012
struct _FATX_BOOTSECTOR * PFATX_BOOTSECTOR
UCHAR Attributes
Definition: fat.h:150
enum _OPENMODE OPENMODE
#define memset(x, y, z)
Definition: compat.h:39
BOOLEAN FatSearchDirectoryBufferForFile(PFAT_VOLUME_INFO Volume, PVOID DirectoryBuffer, ULONG EntryCount, PCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer)
Definition: fat.c:475
LIST_ENTRY DirectoryBufferListHead
Definition: fat.c:386
static unsigned char * fat
Definition: mkdosfs.c:542
ULONG DataSectorStart
Definition: fat.c:55
static PLARGE_INTEGER Time
Definition: time.c:105
base of all file and directory entries
Definition: entries.h:82
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
Iosb Information
Definition: create.c:4377
UCHAR DriveNumber
Definition: bootsup.c:62
ULONG RootDirStartCluster
Definition: bootsup.c:94
USHORT ExtendedFlags
Definition: bootsup.c:92
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186