- Add full FATX support
- Add volume label setting to FAT volumes
- Change all ANSI_STRING to OEM_STRING (thanks Filip!)
- Correct one bug in VfatUpdateEntry
- Correct one bug in VfatShutdown
Fixes bugs 286, 434 and 442

svn path=/trunk/; revision=11946
This commit is contained in:
Gé van Geldorp
2004-12-05 16:31:51 +00:00
parent cb48d72333
commit 44109026ba
14 changed files with 1338 additions and 456 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
/* $Id: cleanup.c,v 1.15 2004/08/28 22:19:12 navaraf Exp $
/* $Id: cleanup.c,v 1.16 2004/12/05 16:31:50 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -35,7 +35,7 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
pFcb = (PVFATFCB) FileObject->FsContext;
if (pFcb)
{
if (!(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) &&
if (!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) &&
FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
{
/* remove all locks this process have on this file */
+58 -30
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: create.c,v 1.75 2004/11/06 13:44:56 ekohl Exp $
/* $Id: create.c,v 1.76 2004/12/05 16:31:50 gvg Exp $
*
* PROJECT: ReactOS kernel
* FILE: drivers/fs/vfat/create.c
@@ -36,10 +36,6 @@
#include "vfat.h"
/* GLOBALS *******************************************************************/
#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry))
/* FUNCTIONS *****************************************************************/
void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
@@ -48,7 +44,7 @@ void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
ULONG Length;
CHAR cString[12];
memcpy(cString, pEntry->Filename, 11);
RtlCopyMemory(cString, pEntry->Filename, 11);
cString[11] = 0;
if (cString[0] == 0x05)
{
@@ -71,7 +67,7 @@ void vfat8Dot3ToString (PFAT_DIR_ENTRY pEntry, PUNICODE_STRING NameU)
{
Length = NameU->Length;
NameU->Buffer += Length / sizeof(WCHAR);
if (!ENTRY_VOLUME(pEntry))
if (!FAT_ENTRY_VOLUME(pEntry))
{
Length += sizeof(WCHAR);
NameU->Buffer[0] = L'.';
@@ -106,16 +102,30 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
{
PVOID Context = NULL;
ULONG DirIndex = 0;
FATDirEntry* Entry;
PDIR_ENTRY Entry;
PVFATFCB pFcb;
LARGE_INTEGER FileOffset;
UNICODE_STRING NameU;
ULONG SizeDirEntry;
ULONG EntriesPerPage;
OEM_STRING StringO;
NameU.Buffer = Vpb->VolumeLabel;
NameU.Length = 0;
NameU.MaximumLength = sizeof(Vpb->VolumeLabel);
*(Vpb->VolumeLabel) = 0;
Vpb->VolumeLabelLength = 0;
if (DeviceExt->Flags & VCB_IS_FATX)
{
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
}
else
{
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
}
ExAcquireResourceExclusiveLite (&DeviceExt->DirResource, TRUE);
pFcb = vfatOpenRootFCB (DeviceExt);
@@ -126,20 +136,29 @@ ReadVolumeLabel (PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
{
while (TRUE)
{
if (ENTRY_VOLUME(Entry))
if (ENTRY_VOLUME(DeviceExt, Entry))
{
/* copy volume label */
vfat8Dot3ToString (Entry, &NameU);
if (DeviceExt->Flags & VCB_IS_FATX)
{
StringO.Buffer = Entry->FatX.Filename;
StringO.MaximumLength = StringO.Length = Entry->FatX.FilenameLength;
RtlOemStringToUnicodeString(&NameU, &StringO, FALSE);
}
else
{
vfat8Dot3ToString (&Entry->Fat, &NameU);
}
Vpb->VolumeLabelLength = NameU.Length;
break;
}
if (ENTRY_END(Entry))
if (ENTRY_END(DeviceExt, Entry))
{
break;
}
DirIndex++;
Entry++;
if ((DirIndex % ENTRIES_PER_PAGE) == 0)
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
if ((DirIndex % EntriesPerPage) == 0)
{
CcUnpinData(Context);
FileOffset.u.LowPart += PAGE_SIZE;
@@ -212,7 +231,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
{
RtlCopyUnicodeString(&DirContext->LongNameU, &rcFcb->LongNameU);
RtlCopyUnicodeString(&DirContext->ShortNameU, &rcFcb->ShortNameU);
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
DirContext->StartIndex = rcFcb->startIndex;
DirContext->DirIndex = rcFcb->dirIndex;
DPRINT("FindFile: new Name %wZ, DirIndex %d (%d)\n",
@@ -231,13 +250,13 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
while(TRUE)
{
Status = vfatGetNextDirEntry(&Context, &Page, Parent, DirContext, First);
Status = DeviceExt->GetNextDirEntry(&Context, &Page, Parent, DirContext, First);
First = FALSE;
if (Status == STATUS_NO_MORE_ENTRIES)
{
break;
}
if (ENTRY_VOLUME(&DirContext->FatDirEntry))
if (ENTRY_VOLUME(DeviceExt, &DirContext->DirEntry))
{
DirContext->DirIndex++;
continue;
@@ -269,7 +288,7 @@ FindFile (PDEVICE_EXTENSION DeviceExt,
rcFcb = vfatGrabFCBFromTable(DeviceExt, &PathNameU);
if (rcFcb != NULL)
{
memcpy(&DirContext->FatDirEntry, &rcFcb->entry, sizeof(FATDirEntry));
RtlCopyMemory(&DirContext->DirEntry, &rcFcb->entry, sizeof(DIR_ENTRY));
vfatReleaseFCB(DeviceExt, rcFcb);
}
}
@@ -407,17 +426,26 @@ VfatSupersedeFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
ULONG Cluster, NextCluster;
NTSTATUS Status;
Fcb->entry.FileSize = 0;
if (DeviceExt->FatInfo.FatType == FAT32)
{
Cluster = Fcb->entry.FirstCluster + Fcb->entry.FirstClusterHigh * 65536;
}
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
Fcb->entry.FatX.FileSize = 0;
Cluster = Fcb->entry.FatX.FirstCluster;
Fcb->entry.FatX.FirstCluster = 0;
}
else
{
Cluster = Fcb->entry.FirstCluster;
}
Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0;
{
Fcb->entry.Fat.FileSize = 0;
if (DeviceExt->FatInfo.FatType == FAT32)
{
Cluster = Fcb->entry.Fat.FirstCluster + Fcb->entry.Fat.FirstClusterHigh * 65536;
}
else
{
Cluster = Fcb->entry.Fat.FirstCluster;
}
Fcb->entry.Fat.FirstCluster = 0;
Fcb->entry.Fat.FirstClusterHigh = 0;
}
Fcb->LastOffset = Fcb->LastCluster = 0;
VfatUpdateEntry (Fcb);
if (Fcb->RFCB.FileSize.QuadPart > 0)
@@ -496,7 +524,7 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
return (STATUS_INSUFFICIENT_RESOURCES);
}
memset(pCcb, 0, sizeof(VFATCCB));
RtlZeroMemory(pCcb, sizeof(VFATCCB));
FileObject->Flags |= FO_FCB_IS_VALID;
FileObject->SectionObjectPointer = &pFcb->SectionObjectPointers;
FileObject->FsContext = pFcb;
@@ -626,13 +654,13 @@ VfatCreateFile (PDEVICE_OBJECT DeviceObject, PIRP Irp)
* Check the file has the requested attributes
*/
if (RequestedOptions & FILE_NON_DIRECTORY_FILE &&
pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
{
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_FILE_IS_A_DIRECTORY);
}
if (RequestedOptions & FILE_DIRECTORY_FILE &&
!(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
!(*pFcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
VfatCloseFile (DeviceExt, FileObject);
return(STATUS_NOT_A_DIRECTORY);
+156 -68
View File
@@ -1,5 +1,5 @@
/*
* $Id: dir.c,v 1.35 2004/11/06 13:44:57 ekohl Exp $
* $Id: dir.c,v 1.36 2004/12/05 16:31:50 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -21,7 +21,7 @@
// function like DosDateTimeToFileTime
BOOL
FsdDosDateTimeToSystemTime (WORD wDosDate, WORD wDosTime, PLARGE_INTEGER SystemTime)
FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt, WORD wDosDate, WORD wDosTime, PLARGE_INTEGER SystemTime)
{
PDOSTIME pdtime = (PDOSTIME) & wDosTime;
PDOSDATE pddate = (PDOSDATE) & wDosDate;
@@ -38,7 +38,7 @@ FsdDosDateTimeToSystemTime (WORD wDosDate, WORD wDosTime, PLARGE_INTEGER SystemT
TimeFields.Day = pddate->Day;
TimeFields.Month = pddate->Month;
TimeFields.Year = 1980 + pddate->Year;
TimeFields.Year = DeviceExt->BaseDateYear + pddate->Year;
RtlTimeFieldsToTime (&TimeFields, &LocalTime);
ExLocalTimeToSystemTime(&LocalTime, SystemTime);
@@ -46,10 +46,9 @@ FsdDosDateTimeToSystemTime (WORD wDosDate, WORD wDosTime, PLARGE_INTEGER SystemT
return TRUE;
}
// function like FileTimeToDosDateTime
BOOL
FsdSystemTimeToDosDateTime (PLARGE_INTEGER SystemTime, WORD * pwDosDate, WORD * pwDosTime)
FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt, PLARGE_INTEGER SystemTime, WORD * pwDosDate, WORD * pwDosTime)
{
PDOSTIME pdtime = (PDOSTIME) pwDosTime;
PDOSDATE pddate = (PDOSDATE) pwDosDate;
@@ -73,13 +72,12 @@ FsdSystemTimeToDosDateTime (PLARGE_INTEGER SystemTime, WORD * pwDosDate, WORD *
{
pddate->Day = TimeFields.Day;
pddate->Month = TimeFields.Month;
pddate->Year = TimeFields.Year - 1980;
pddate->Year = TimeFields.Year - DeviceExt->BaseDateYear;
}
return TRUE;
}
#define DWORD_ROUND_UP(x) ROUND_UP((x), (sizeof(DWORD)))
NTSTATUS
@@ -91,7 +89,7 @@ VfatGetFileNameInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
return STATUS_SUCCESS;
}
@@ -106,31 +104,61 @@ VfatGetFileDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationTime,
if (DeviceExt->Flags & VCB_IS_FATX)
{
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.AccessDate, 0,
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime,
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->FatDirEntry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib & 0x3f;
{
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate, 0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
}
return STATUS_SUCCESS;
}
@@ -146,23 +174,45 @@ VfatGetFileFullDirectoryInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_FULL_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationTime,
if (DeviceExt->Flags & VCB_IS_FATX)
{
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.AccessDate,
0, &pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime,
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib & 0x3f;
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate,
0, &pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
}
// pInfo->EaSize=;
return STATUS_SUCCESS;
}
@@ -175,36 +225,74 @@ VfatGetFileBothInformation (PVFAT_DIRENTRY_CONTEXT DirContext,
{
if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length) > BufferLength)
return STATUS_BUFFER_OVERFLOW;
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
memcpy(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
pInfo->ShortNameLength = DirContext->ShortNameU.Length;
memcpy (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.CreationDate,
DirContext->FatDirEntry.CreationDate,
if (DeviceExt->Flags & VCB_IS_FATX)
{
pInfo->FileNameLength = DirContext->LongNameU.Length;
RtlCopyMemory(pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
pInfo->ShortName[0] = 0;
pInfo->ShortNameLength = 0;
// pInfo->FileIndex=;
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.CreationDate,
DirContext->DirEntry.FatX.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.AccessDate, 0,
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.AccessDate,
DirContext->DirEntry.FatX.AccessTime,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DirContext->FatDirEntry.UpdateDate,
DirContext->FatDirEntry.UpdateTime,
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.FatX.UpdateDate,
DirContext->DirEntry.FatX.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->FatDirEntry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->DirEntry.FatX.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.FatX.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.FatX.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.FatX.Attrib & 0x3f;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->FatDirEntry.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->FatDirEntry.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->FatDirEntry.Attrib & 0x3f;
{
pInfo->FileNameLength = DirContext->LongNameU.Length;
pInfo->NextEntryOffset =
DWORD_ROUND_UP (sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + DirContext->LongNameU.Length);
RtlCopyMemory(pInfo->ShortName, DirContext->ShortNameU.Buffer, DirContext->ShortNameU.Length);
pInfo->ShortNameLength = DirContext->ShortNameU.Length;
RtlCopyMemory (pInfo->FileName, DirContext->LongNameU.Buffer, DirContext->LongNameU.Length);
// pInfo->FileIndex=;
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.CreationDate,
DirContext->DirEntry.Fat.CreationTime,
&pInfo->CreationTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.AccessDate, 0,
&pInfo->LastAccessTime);
FsdDosDateTimeToSystemTime (DeviceExt, DirContext->DirEntry.Fat.UpdateDate,
DirContext->DirEntry.Fat.UpdateTime,
&pInfo->LastWriteTime);
pInfo->ChangeTime = pInfo->LastWriteTime;
if (DirContext->DirEntry.Fat.Attrib & FILE_ATTRIBUTE_DIRECTORY)
{
pInfo->EndOfFile.QuadPart = 0LL;
pInfo->AllocationSize.QuadPart = 0LL;
}
else
{
pInfo->EndOfFile.u.HighPart = 0;
pInfo->EndOfFile.u.LowPart = DirContext->DirEntry.Fat.FileSize;
/* Make allocsize a rounded up multiple of BytesPerCluster */
pInfo->AllocationSize.u.HighPart = 0;
pInfo->AllocationSize.u.LowPart = ROUND_UP(DirContext->DirEntry.Fat.FileSize, DeviceExt->FatInfo.BytesPerCluster);
}
pInfo->FileAttributes = DirContext->DirEntry.Fat.Attrib & 0x3f;
}
pInfo->EaSize=0;
return STATUS_SUCCESS;
}
+201 -38
View File
@@ -1,4 +1,4 @@
/* $Id: direntry.c,v 1.17 2004/08/01 21:57:17 navaraf Exp $
/* $Id: direntry.c,v 1.18 2004/12/05 16:31:50 gvg Exp $
*
*
* FILE: DirEntry.c
@@ -8,6 +8,7 @@
* PROGRAMMER: Jason Filby ([email protected])
* Rex Jolliff ([email protected])
* Hartmut Birr
* Herve Poussineau ([email protected])
*/
/* ------------------------------------------------------- INCLUDES */
@@ -21,28 +22,30 @@
#include "vfat.h"
#define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATDirEntry))
ULONG
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pFatDirEntry)
PDIR_ENTRY pFatDirEntry)
{
ULONG cluster;
if (pDeviceExt->FatInfo.FatType == FAT32)
{
cluster = pFatDirEntry->FirstCluster +
pFatDirEntry->FirstClusterHigh * 65536;
cluster = pFatDirEntry->Fat.FirstCluster +
pFatDirEntry->Fat.FirstClusterHigh * 65536;
}
else if (pDeviceExt->Flags & VCB_IS_FATX)
{
cluster = pFatDirEntry->FatX.FirstCluster;
}
else
{
cluster = pFatDirEntry->FirstCluster;
cluster = pFatDirEntry->Fat.FirstCluster;
}
return cluster;
}
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
BOOL FATIsDirectoryEmpty(PVFATFCB Fcb)
{
LARGE_INTEGER FileOffset;
PVOID Context = NULL;
@@ -63,7 +66,7 @@ BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
while (Index < MaxIndex)
{
if (Context == NULL || (Index % ENTRIES_PER_PAGE) == 0)
if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0)
{
if (Context != NULL)
{
@@ -73,14 +76,14 @@ BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
{
return TRUE;
}
FatDirEntry += Index % ENTRIES_PER_PAGE;
FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
}
if (ENTRY_END(FatDirEntry))
if (FAT_ENTRY_END(FatDirEntry))
{
CcUnpinData(Context);
return TRUE;
}
if (!ENTRY_DELETED(FatDirEntry))
if (!FAT_ENTRY_DELETED(FatDirEntry))
{
CcUnpinData(Context);
return FALSE;
@@ -95,7 +98,61 @@ BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
return TRUE;
}
NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
BOOL FATXIsDirectoryEmpty(PVFATFCB Fcb)
{
LARGE_INTEGER FileOffset;
PVOID Context = NULL;
PFATX_DIR_ENTRY FatXDirEntry;
ULONG Index, MaxIndex;
Index = 0;
FileOffset.QuadPart = 0LL;
MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FATX_DIR_ENTRY);
while (Index < MaxIndex)
{
if (Context == NULL || (Index % FATX_ENTRIES_PER_PAGE) == 0)
{
if (Context != NULL)
{
CcUnpinData(Context);
}
if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatXDirEntry))
{
return TRUE;
}
FatXDirEntry += Index % FATX_ENTRIES_PER_PAGE;
}
if (FATX_ENTRY_END(FatXDirEntry))
{
CcUnpinData(Context);
return TRUE;
}
if (!FATX_ENTRY_DELETED(FatXDirEntry))
{
CcUnpinData(Context);
return FALSE;
}
Index++;
FatXDirEntry++;
}
if (Context)
{
CcUnpinData(Context);
}
return TRUE;
}
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb)
{
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
return FATXIsDirectoryEmpty(Fcb);
else
return FATIsDirectoryEmpty(Fcb);
}
NTSTATUS FATGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
PVFAT_DIRENTRY_CONTEXT DirContext,
@@ -104,7 +161,7 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
ULONG dirMap;
PWCHAR pName;
LARGE_INTEGER FileOffset;
FATDirEntry * fatDirEntry;
PFAT_DIR_ENTRY fatDirEntry;
slot * longNameEntry;
ULONG index;
@@ -116,9 +173,9 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
DirContext->LongNameU.Buffer[0] = 0;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FATDirEntry), PAGE_SIZE);
FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FAT_DIR_ENTRY), PAGE_SIZE);
if (*pContext == NULL || (DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
if (*pContext == NULL || (DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
{
if (*pContext != NULL)
{
@@ -132,7 +189,7 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
}
fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry;
dirMap = 0;
@@ -142,14 +199,14 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
* into a long name or points to a short name with an assigned long name.
* We must go back to the real start of the entry */
while (DirContext->DirIndex > 0 &&
!ENTRY_END(fatDirEntry) &&
!ENTRY_DELETED(fatDirEntry) &&
((!ENTRY_LONG(fatDirEntry) && !Back) ||
(ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40))))
!FAT_ENTRY_END(fatDirEntry) &&
!FAT_ENTRY_DELETED(fatDirEntry) &&
((!FAT_ENTRY_LONG(fatDirEntry) && !Back) ||
(FAT_ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40))))
{
DirContext->DirIndex--;
Back = TRUE;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == ENTRIES_PER_PAGE - 1)
if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == FAT_ENTRIES_PER_PAGE - 1)
{
CcUnpinData(*pContext);
FileOffset.u.LowPart -= PAGE_SIZE;
@@ -159,7 +216,7 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
fatDirEntry = (FATDirEntry*)(*pPage) + DirContext->DirIndex % ENTRIES_PER_PAGE;
fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry;
}
else
@@ -169,11 +226,11 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
}
}
if (Back && !ENTRY_END(fatDirEntry) &&
(ENTRY_DELETED(fatDirEntry) || !ENTRY_LONG(fatDirEntry)))
if (Back && !FAT_ENTRY_END(fatDirEntry) &&
(FAT_ENTRY_DELETED(fatDirEntry) || !FAT_ENTRY_LONG(fatDirEntry)))
{
DirContext->DirIndex++;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
{
CcUnpinData(*pContext);
FileOffset.u.LowPart += PAGE_SIZE;
@@ -183,7 +240,7 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
fatDirEntry = (FATDirEntry*)*pPage;
fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
longNameEntry = (slot*) *pPage;
}
else
@@ -199,14 +256,14 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
while (TRUE)
{
if (ENTRY_END(fatDirEntry))
if (FAT_ENTRY_END(fatDirEntry))
{
CcUnpinData(*pContext);
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
if (ENTRY_DELETED(fatDirEntry))
if (FAT_ENTRY_DELETED(fatDirEntry))
{
dirMap = 0;
DirContext->LongNameU.Buffer[0] = 0;
@@ -214,12 +271,12 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
}
else
{
if (ENTRY_LONG(fatDirEntry))
if (FAT_ENTRY_LONG(fatDirEntry))
{
if (dirMap == 0)
{
DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
memset(DirContext->LongNameU.Buffer, 0, DirContext->LongNameU.MaximumLength);
RtlZeroMemory(DirContext->LongNameU.Buffer, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
}
@@ -233,9 +290,9 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
dirMap |= 1 << index;
pName = DirContext->LongNameU.Buffer + 13 * index;
memcpy(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
memcpy(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
memcpy(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
RtlCopyMemory(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
RtlCopyMemory(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
RtlCopyMemory(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
DPRINT (" longName: [%S]\n", DirContext->LongNameU.Buffer);
if (CheckSum != longNameEntry->alias_checksum)
@@ -265,12 +322,12 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
DirContext->LongNameU.Buffer[0] = 0;
}
memcpy (&DirContext->FatDirEntry, fatDirEntry, sizeof (FAT_DIR_ENTRY));
RtlCopyMemory (&DirContext->DirEntry.Fat, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
DirContext->DirIndex++;
if ((DirContext->DirIndex % ENTRIES_PER_PAGE) == 0)
if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
{
CcUnpinData(*pContext);
FileOffset.u.LowPart += PAGE_SIZE;
@@ -280,7 +337,7 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
fatDirEntry = (FATDirEntry*)*pPage;
fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
longNameEntry = (slot*) *pPage;
}
else
@@ -290,10 +347,116 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
}
}
DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR);
vfat8Dot3ToString(&DirContext->FatDirEntry, &DirContext->ShortNameU);
vfat8Dot3ToString(&DirContext->DirEntry.Fat, &DirContext->ShortNameU);
if (DirContext->LongNameU.Length == 0)
{
RtlCopyUnicodeString(&DirContext->LongNameU, &DirContext->ShortNameU);
}
return STATUS_SUCCESS;
}
NTSTATUS FATXGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First)
{
LARGE_INTEGER FileOffset;
PFATX_DIR_ENTRY fatxDirEntry;
OEM_STRING StringO;
ULONG DirIndex = DirContext->DirIndex;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE);
if (!vfatFCBIsRoot(pDirFcb))
{
/* need to add . and .. entries */
switch (DirContext->DirIndex)
{
case 0: /* entry . */
{
DirContext->ShortNameU.Buffer[0] = 0;
DirContext->ShortNameU.Length = 0;
DirContext->LongNameU.Buffer[0] = L'.';
DirContext->LongNameU.Length = sizeof(WCHAR);
RtlCopyMemory(&DirContext->DirEntry.FatX, &pDirFcb->entry.FatX, sizeof(FATX_DIR_ENTRY));
DirContext->DirEntry.FatX.Filename[0] = '.';
DirContext->DirEntry.FatX.FilenameLength = 1;
DirContext->StartIndex = 0;
return STATUS_SUCCESS;
}
case 1: /* entry .. */
{
DirContext->ShortNameU.Buffer[0] = 0;
DirContext->ShortNameU.Length = 0;
DirContext->LongNameU.Buffer[0] = DirContext->LongNameU.Buffer[1] = L'.';
DirContext->LongNameU.Length = 2 * sizeof(WCHAR);
RtlCopyMemory(&DirContext->DirEntry.FatX, &pDirFcb->entry.FatX, sizeof(FATX_DIR_ENTRY));
DirContext->DirEntry.FatX.Filename[0] = DirContext->DirEntry.FatX.Filename[1] = '.';
DirContext->DirEntry.FatX.FilenameLength = 2;
DirContext->StartIndex = 1;
return STATUS_SUCCESS;
}
default:
DirIndex -= 2;
}
}
if (*pContext == NULL || (DirIndex % FATX_ENTRIES_PER_PAGE) == 0)
{
if (*pContext != NULL)
{
CcUnpinData(*pContext);
}
if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
}
fatxDirEntry = (PFATX_DIR_ENTRY)(*pPage) + DirIndex % FATX_ENTRIES_PER_PAGE;
DirContext->StartIndex = DirIndex;
while (TRUE)
{
if (FATX_ENTRY_END(fatxDirEntry))
{
CcUnpinData(*pContext);
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
if (!FATX_ENTRY_DELETED(fatxDirEntry))
{
RtlCopyMemory(&DirContext->DirEntry.FatX, fatxDirEntry, sizeof(FATX_DIR_ENTRY));
break;
}
DirContext->DirIndex++;
DirContext->StartIndex++;
if ((DirContext->DirIndex % FATX_ENTRIES_PER_PAGE) == 0)
{
CcUnpinData(*pContext);
FileOffset.u.LowPart += PAGE_SIZE;
if (!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{
CHECKPOINT;
*pContext = NULL;
return STATUS_NO_MORE_ENTRIES;
}
fatxDirEntry = (PFATX_DIR_ENTRY)*pPage;
}
else
{
fatxDirEntry++;
}
}
DirContext->ShortNameU.Buffer[0] = 0;
DirContext->ShortNameU.Length = 0;
StringO.Buffer = fatxDirEntry->Filename;
StringO.Length = StringO.MaximumLength = fatxDirEntry->FilenameLength;
RtlOemStringToUnicodeString(&DirContext->LongNameU, &StringO, FALSE);
return STATUS_SUCCESS;
}
+274 -82
View File
@@ -1,4 +1,4 @@
/* $Id: dirwr.c,v 1.42 2004/11/06 13:44:57 ekohl Exp $
/* $Id: dirwr.c,v 1.43 2004/12/05 16:31:50 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -26,21 +26,34 @@ VfatUpdateEntry (PVFATFCB pFcb)
*/
{
PVOID Context;
PFAT_DIR_ENTRY PinEntry;
PDIR_ENTRY PinEntry;
LARGE_INTEGER Offset;
ULONG SizeDirEntry;
ULONG dirIndex;
ASSERT(pFcb);
ASSERT(pFcb->parentFcb);
if (pFcb->Flags & FCB_IS_FATX_ENTRY)
{
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
dirIndex = pFcb->startIndex;
}
else
{
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
dirIndex = pFcb->dirIndex;
}
DPRINT ("updEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
DPRINT ("updEntry dirIndex %d, PathName \'%wZ\'\n", dirIndex, &pFcb->PathNameU);
Offset.u.HighPart = 0;
Offset.u.LowPart = pFcb->dirIndex * sizeof(FATDirEntry);
if (CcMapData (pFcb->parentFcb->FileObject, &Offset, sizeof(FATDirEntry),
Offset.u.LowPart = dirIndex * SizeDirEntry;
if (CcMapData (pFcb->parentFcb->FileObject, &Offset, SizeDirEntry,
TRUE, &Context, (PVOID*)&PinEntry))
{
pFcb->Flags &= ~FCB_IS_DIRTY;
*PinEntry = pFcb->entry;
RtlCopyMemory(PinEntry, &pFcb->entry, SizeDirEntry);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
return STATUS_SUCCESS;
@@ -64,13 +77,20 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
*/
LARGE_INTEGER FileOffset;
ULONG i, count, size, nbFree = 0;
FATDirEntry* pFatEntry;
PDIR_ENTRY pFatEntry;
PVOID Context = NULL;
NTSTATUS Status;
ULONG SizeDirEntry;
FileOffset.QuadPart = 0;
count = pDirFcb->RFCB.FileSize.u.LowPart / sizeof(FATDirEntry);
size = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
for (i = 0; i < count; i++, pFatEntry++)
if (DeviceExt->Flags & VCB_IS_FATX)
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
else
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
count = pDirFcb->RFCB.FileSize.u.LowPart / SizeDirEntry;
size = DeviceExt->FatInfo.BytesPerCluster / SizeDirEntry;
for (i = 0; i < count; i++, pFatEntry = (PDIR_ENTRY)((ULONG_PTR)pFatEntry + SizeDirEntry))
{
if (Context == NULL || (i % size) == 0)
{
@@ -83,11 +103,11 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
TRUE, &Context, (PVOID*)&pFatEntry);
FileOffset.u.LowPart += DeviceExt->FatInfo.BytesPerCluster;
}
if (ENTRY_END(pFatEntry))
if (ENTRY_END(DeviceExt, pFatEntry))
{
break;
}
if (ENTRY_DELETED(pFatEntry))
if (ENTRY_DELETED(DeviceExt, pFatEntry))
{
nbFree++;
}
@@ -120,7 +140,7 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
// extend the directory
if (vfatFCBIsRoot(pDirFcb) && DeviceExt->FatInfo.FatType != FAT32)
{
// We can't extend a root directory on a FAT12/FAT16 partition
// We can't extend a root directory on a FAT12/FAT16/FATX partition
return FALSE;
}
AllocationSize.QuadPart = pDirFcb->RFCB.FileSize.u.LowPart + DeviceExt->FatInfo.BytesPerCluster;
@@ -135,15 +155,21 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
DeviceExt->FatInfo.BytesPerCluster);
CcMapData (pDirFcb->FileObject, &FileOffset, DeviceExt->FatInfo.BytesPerCluster,
TRUE, &Context, (PVOID*)&pFatEntry);
RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
if (DeviceExt->Flags & VCB_IS_FATX)
memset(pFatEntry, 0xff, DeviceExt->FatInfo.BytesPerCluster);
else
RtlZeroMemory(pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
}
else if (*start + nbSlots < count)
{
// clear the entry after the last new entry
FileOffset.u.LowPart = (*start + nbSlots) * sizeof(FATDirEntry);
CcMapData (pDirFcb->FileObject, &FileOffset, sizeof(FATDirEntry),
FileOffset.u.LowPart = (*start + nbSlots) * SizeDirEntry;
CcMapData (pDirFcb->FileObject, &FileOffset, SizeDirEntry,
TRUE, &Context, (PVOID*)&pFatEntry);
RtlZeroMemory(pFatEntry, sizeof(FATDirEntry));
if (DeviceExt->Flags & VCB_IS_FATX)
memset(pFatEntry, 0xff, SizeDirEntry);
else
RtlZeroMemory(pFatEntry, SizeDirEntry);
}
if (Context)
{
@@ -156,7 +182,7 @@ vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
}
NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
FATAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject,
ULONG RequestedOptions,
@@ -166,7 +192,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
*/
{
PVOID Context = NULL;
FATDirEntry *pFatEntry;
PFAT_DIR_ENTRY pFatEntry;
slot *pSlots;
short nbSlots = 0, j, posCar;
PUCHAR Buffer;
@@ -180,7 +206,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
ULONG size;
long i;
ANSI_STRING NameA;
OEM_STRING NameA;
CHAR aName[13];
BOOLEAN IsNameLegal;
BOOLEAN SpacesFound;
@@ -212,8 +238,8 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
nbSlots = (DirContext.LongNameU.Length / sizeof(WCHAR) + 12) / 13 + 1; //nb of entry needed for long name+normal entry
DPRINT ("NameLen= %d, nbSlots =%d\n", DirContext.LongNameU.Length / sizeof(WCHAR), nbSlots);
Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FATDirEntry));
RtlZeroMemory (Buffer, (nbSlots - 1) * sizeof (FATDirEntry));
Buffer = ExAllocatePool (NonPagedPool, (nbSlots - 1) * sizeof (FAT_DIR_ENTRY));
RtlZeroMemory (Buffer, (nbSlots - 1) * sizeof (FAT_DIR_ENTRY));
pSlots = (slot *) Buffer;
NameA.Buffer = aName;
@@ -224,7 +250,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = sizeof(ShortNameBuffer);
memset(&DirContext.FatDirEntry, 0, sizeof(FATDirEntry));
RtlZeroMemory(&DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.LongNameU, &NameA, &SpacesFound);
@@ -235,7 +261,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
WCHAR ShortSearchName[13];
needTilde = TRUE;
needLong = TRUE;
memset(&NameContext, 0, sizeof(GENERATE_NAME_CONTEXT));
RtlZeroMemory(&NameContext, sizeof(GENERATE_NAME_CONTEXT));
SearchContext.LongNameU.Buffer = LongNameBuffer;
SearchContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
SearchContext.ShortNameU.Buffer = ShortSearchName;
@@ -257,7 +283,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
ExReleaseResourceLite(&pDirFcb->MainResource);
vfatReleaseFCB(DeviceExt, pDirFcb);
ExFreePool (Buffer);
CHECKPOINT;
CHECKPOINT;
return STATUS_UNSUCCESSFUL;
}
IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound);
@@ -310,27 +336,27 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
}
DPRINT ("'%s', '%wZ', needTilde=%d, needLong=%d\n",
aName, &DirContext.LongNameU, needTilde, needLong);
memset(DirContext.FatDirEntry.Filename, ' ', 11);
memset(DirContext.DirEntry.Fat.Filename, ' ', 11);
for (i = 0; i < 8 && aName[i] && aName[i] != '.'; i++)
{
DirContext.FatDirEntry.Filename[i] = aName[i];
DirContext.DirEntry.Fat.Filename[i] = aName[i];
}
if (aName[i] == '.')
{
i++;
for (j = 8; j < 11 && aName[i]; j++, i++)
{
DirContext.FatDirEntry.Filename[j] = aName[i];
DirContext.DirEntry.Fat.Filename[j] = aName[i];
}
}
if (DirContext.FatDirEntry.Filename[0] == 0xe5)
if (DirContext.DirEntry.Fat.Filename[0] == 0xe5)
{
DirContext.FatDirEntry.Filename[0] = 0x05;
DirContext.DirEntry.Fat.Filename[0] = 0x05;
}
if (needLong)
{
memcpy(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
RtlCopyMemory(LongNameBuffer, DirContext.LongNameU.Buffer, DirContext.LongNameU.Length);
DirContext.LongNameU.Buffer = LongNameBuffer;
DirContext.LongNameU.MaximumLength = sizeof(LongNameBuffer);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
@@ -342,39 +368,29 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
nbSlots = 1;
if (lCaseBase)
{
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_BASE;
DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_BASE;
}
if (lCaseExt)
{
DirContext.FatDirEntry.lCase |= VFAT_CASE_LOWER_EXT;
DirContext.DirEntry.Fat.lCase |= VFAT_CASE_LOWER_EXT;
}
}
DPRINT ("dos name=%11.11s\n", DirContext.FatDirEntry.Filename);
DPRINT ("dos name=%11.11s\n", DirContext.DirEntry.Fat.Filename);
/* set attributes */
DirContext.FatDirEntry.Attrib = ReqAttr;
DirContext.DirEntry.Fat.Attrib = ReqAttr;
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
DirContext.FatDirEntry.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
DirContext.DirEntry.Fat.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
}
/* set dates and times */
KeQuerySystemTime (&SystemTime);
#if 0
{
TIME_FIELDS tf;
RtlTimeToTimeFields (&SystemTime, &tf);
DPRINT1("%d.%d.%d %02d:%02d:%02d.%03d '%S'\n",
tf.Day, tf.Month, tf.Year, tf.Hour,
tf.Minute, tf.Second, tf.Milliseconds,
pFileObject->FileName.Buffer);
}
#endif
FsdSystemTimeToDosDateTime (&SystemTime, &DirContext.FatDirEntry.CreationDate,
&DirContext.FatDirEntry.CreationTime);
DirContext.FatDirEntry.UpdateDate = DirContext.FatDirEntry.CreationDate;
DirContext.FatDirEntry.UpdateTime = DirContext.FatDirEntry.CreationTime;
DirContext.FatDirEntry.AccessDate = DirContext.FatDirEntry.CreationDate;
FsdSystemTimeToDosDateTime (DeviceExt, &SystemTime, &DirContext.DirEntry.Fat.CreationDate,
&DirContext.DirEntry.Fat.CreationTime);
DirContext.DirEntry.Fat.UpdateDate = DirContext.DirEntry.Fat.CreationDate;
DirContext.DirEntry.Fat.UpdateTime = DirContext.DirEntry.Fat.CreationTime;
DirContext.DirEntry.Fat.AccessDate = DirContext.DirEntry.Fat.CreationDate;
if (needLong)
{
@@ -383,7 +399,7 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
{
pSlots[0].alias_checksum = (((pSlots[0].alias_checksum & 1) << 7
| ((pSlots[0].alias_checksum & 0xfe) >> 1))
+ DirContext.FatDirEntry.Filename[i]);
+ DirContext.DirEntry.Fat.Filename[i]);
}
/* construct slots and entry */
for (i = nbSlots - 2; i >= 0; i--)
@@ -399,9 +415,9 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
pSlots[i].id = nbSlots - i - 1 + 0x40;
}
pSlots[i].alias_checksum = pSlots[0].alias_checksum;
memcpy (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
memcpy (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
memcpy (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
RtlCopyMemory (pSlots[i].name0_4, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13, 10);
RtlCopyMemory (pSlots[i].name5_10, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 5, 12);
RtlCopyMemory (pSlots[i].name11_12, DirContext.LongNameU.Buffer + (nbSlots - i - 2) * 13 + 11, 4);
}
}
/* try to find nbSlots contiguous entries frees in directory */
@@ -430,47 +446,47 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
}
if (DeviceExt->FatInfo.FatType == FAT32)
{
DirContext.FatDirEntry.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
DirContext.DirEntry.Fat.FirstClusterHigh = (unsigned short)(CurrentCluster >> 16);
}
DirContext.FatDirEntry.FirstCluster = (unsigned short)CurrentCluster;
DirContext.DirEntry.Fat.FirstCluster = (unsigned short)CurrentCluster;
}
i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FATDirEntry);
i = DeviceExt->FatInfo.BytesPerCluster / sizeof(FAT_DIR_ENTRY);
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATDirEntry);
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FAT_DIR_ENTRY);
if (DirContext.StartIndex / i == DirContext.DirIndex / i)
{
/* one cluster */
CHECKPOINT;
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FATDirEntry),
CcMapData (pDirFcb->FileObject, &FileOffset, nbSlots * sizeof(FAT_DIR_ENTRY),
TRUE, &Context, (PVOID*)&pFatEntry);
if (nbSlots > 1)
{
memcpy(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FATDirEntry));
RtlCopyMemory(pFatEntry, Buffer, (nbSlots - 1) * sizeof(FAT_DIR_ENTRY));
}
memcpy(pFatEntry + (nbSlots - 1), &DirContext.FatDirEntry, sizeof(FATDirEntry));
RtlCopyMemory(pFatEntry + (nbSlots - 1), &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
}
else
{
/* two clusters */
CHECKPOINT;
size = DeviceExt->FatInfo.BytesPerCluster -
(DirContext.StartIndex * sizeof(FATDirEntry)) % DeviceExt->FatInfo.BytesPerCluster;
i = size / sizeof(FATDirEntry);
(DirContext.StartIndex * sizeof(FAT_DIR_ENTRY)) % DeviceExt->FatInfo.BytesPerCluster;
i = size / sizeof(FAT_DIR_ENTRY);
CcMapData (pDirFcb->FileObject, &FileOffset, size, TRUE,
&Context, (PVOID*)&pFatEntry);
memcpy(pFatEntry, Buffer, size);
RtlCopyMemory(pFatEntry, Buffer, size);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
FileOffset.u.LowPart += size;
CcMapData (pDirFcb->FileObject, &FileOffset,
nbSlots * sizeof(FATDirEntry) - size,
nbSlots * sizeof(FAT_DIR_ENTRY) - size,
TRUE, &Context, (PVOID*)&pFatEntry);
if (nbSlots - 1 > i)
{
memcpy(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FATDirEntry));
RtlCopyMemory(pFatEntry, (PVOID)(Buffer + size), (nbSlots - 1 - i) * sizeof(FAT_DIR_ENTRY));
}
memcpy(pFatEntry + nbSlots - 1 - i, &DirContext.FatDirEntry, sizeof(FATDirEntry));
RtlCopyMemory(pFatEntry + nbSlots - 1 - i, &DirContext.DirEntry.Fat, sizeof(FAT_DIR_ENTRY));
}
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
@@ -479,8 +495,8 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
vfatMakeFCBFromDirEntry (DeviceExt, pDirFcb, &DirContext, &newFCB);
vfatAttachFCBToFileObject (DeviceExt, newFCB, pFileObject);
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Filename);
DPRINT ("new : entry=%11.11s\n", DirContext.FatDirEntry.Filename);
DPRINT ("new : entry=%11.11s\n", newFCB->entry.Fat.Filename);
DPRINT ("new : entry=%11.11s\n", DirContext.DirEntry.Fat.Filename);
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
@@ -490,12 +506,12 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
/* clear the new directory cluster */
RtlZeroMemory (pFatEntry, DeviceExt->FatInfo.BytesPerCluster);
/* create '.' and '..' */
memcpy (&pFatEntry[0].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[0].Filename, ". ", 11);
memcpy (&pFatEntry[1].Attrib, &DirContext.FatDirEntry.Attrib, sizeof(FATDirEntry) - 11);
memcpy (pFatEntry[1].Filename, ".. ", 11);
pFatEntry[1].FirstCluster = pDirFcb->entry.FirstCluster;
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.FirstClusterHigh;
RtlCopyMemory (&pFatEntry[0].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
RtlCopyMemory (pFatEntry[0].Filename, ". ", 11);
RtlCopyMemory (&pFatEntry[1].Attrib, &DirContext.DirEntry.Fat.Attrib, sizeof(FAT_DIR_ENTRY) - 11);
RtlCopyMemory (pFatEntry[1].Filename, ".. ", 11);
pFatEntry[1].FirstCluster = pDirFcb->entry.Fat.FirstCluster;
pFatEntry[1].FirstClusterHigh = pDirFcb->entry.Fat.FirstClusterHigh;
if (vfatFCBIsRoot(pDirFcb))
{
pFatEntry[1].FirstCluster = 0;
@@ -512,7 +528,129 @@ VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
}
NTSTATUS
VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
FATXAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject,
ULONG RequestedOptions,
UCHAR ReqAttr)
/*
create a new FAT entry
*/
{
PVOID Context = NULL;
PVFATFCB newFCB;
LARGE_INTEGER SystemTime, FileOffset;
PVFATFCB pDirFcb;
OEM_STRING NameA;
VFAT_DIRENTRY_CONTEXT DirContext;
PFATX_DIR_ENTRY pFatXDirEntry;
UNICODE_STRING DirNameU;
DPRINT ("addEntry: Pathname='%wZ'\n", PathNameU);
vfatSplitPathName(PathNameU, &DirNameU, &DirContext.LongNameU);
if (DirNameU.Length > sizeof(WCHAR))
{
DirNameU.Length -= sizeof(WCHAR);
}
if (DirContext.LongNameU.Length / sizeof(WCHAR) > 42)
{
/* name too long */
CHECKPOINT;
return STATUS_NAME_TOO_LONG;
}
pDirFcb = vfatGrabFCBFromTable(DeviceExt, &DirNameU);
if (pDirFcb == NULL)
{
return STATUS_UNSUCCESSFUL;
}
if (!ExAcquireResourceExclusiveLite(&pDirFcb->MainResource, TRUE))
{
DPRINT("Failed acquiring lock\n");
return STATUS_UNSUCCESSFUL;
}
/* try to find 1 entry free in directory */
if (!vfatFindDirSpace(DeviceExt, pDirFcb, 1, &DirContext.StartIndex))
{
ExReleaseResourceLite(&pDirFcb->MainResource);
vfatReleaseFCB(DeviceExt, pDirFcb);
return STATUS_DISK_FULL;
}
DirContext.DirIndex = DirContext.StartIndex;
if (!vfatFCBIsRoot(pDirFcb))
{
DirContext.DirIndex += 2;
}
DirContext.ShortNameU.Buffer = 0;
DirContext.ShortNameU.Length = 0;
DirContext.ShortNameU.MaximumLength = 0;
RtlZeroMemory(&DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
memset(DirContext.DirEntry.FatX.Filename, 0xff, 42);
DirContext.DirEntry.FatX.FirstCluster = 0;
DirContext.DirEntry.FatX.FileSize = 0;
/* set file name */
NameA.Buffer = DirContext.DirEntry.FatX.Filename;
NameA.Length = 0;
NameA.MaximumLength = 42;
RtlUnicodeStringToOemString(&NameA, &DirContext.LongNameU, FALSE);
DirContext.DirEntry.FatX.FilenameLength = NameA.Length;
/* set attributes */
DirContext.DirEntry.FatX.Attrib = ReqAttr;
if (RequestedOptions & FILE_DIRECTORY_FILE)
{
DirContext.DirEntry.FatX.Attrib |= FILE_ATTRIBUTE_DIRECTORY;
}
/* set dates and times */
KeQuerySystemTime (&SystemTime);
FsdSystemTimeToDosDateTime(DeviceExt, &SystemTime, &DirContext.DirEntry.FatX.CreationDate,
&DirContext.DirEntry.FatX.CreationTime);
DirContext.DirEntry.FatX.UpdateDate = DirContext.DirEntry.FatX.CreationDate;
DirContext.DirEntry.FatX.UpdateTime = DirContext.DirEntry.FatX.CreationTime;
DirContext.DirEntry.FatX.AccessDate = DirContext.DirEntry.FatX.CreationDate;
DirContext.DirEntry.FatX.AccessTime = DirContext.DirEntry.FatX.CreationTime;
/* add entry into parent directory */
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = DirContext.StartIndex * sizeof(FATX_DIR_ENTRY);
CcMapData(pDirFcb->FileObject, &FileOffset, sizeof(FATX_DIR_ENTRY),
TRUE, &Context, (PVOID*)&pFatXDirEntry);
RtlCopyMemory(pFatXDirEntry, &DirContext.DirEntry.FatX, sizeof(FATX_DIR_ENTRY));
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
/* FIXME: check status */
vfatMakeFCBFromDirEntry(DeviceExt, pDirFcb, &DirContext, &newFCB);
vfatAttachFCBToFileObject(DeviceExt, newFCB, pFileObject);
ExReleaseResourceLite(&pDirFcb->MainResource);
vfatReleaseFCB(DeviceExt, pDirFcb);
DPRINT("addentry ok\n");
return STATUS_SUCCESS;
}
NTSTATUS
VfatAddEntry (PDEVICE_EXTENSION DeviceExt,
PUNICODE_STRING PathNameU,
PFILE_OBJECT pFileObject,
ULONG RequestedOptions,
UCHAR ReqAttr)
{
if (DeviceExt->Flags & VCB_IS_FATX)
return FATXAddEntry(DeviceExt, PathNameU, pFileObject, RequestedOptions, ReqAttr);
else
return FATAddEntry(DeviceExt, PathNameU, pFileObject, RequestedOptions, ReqAttr);
}
NTSTATUS
FATDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/*
* deleting an existing FAT entry
*/
@@ -520,7 +658,7 @@ VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
ULONG CurrentCluster = 0, NextCluster, i;
PVOID Context = NULL;
LARGE_INTEGER Offset;
FATDirEntry* pDirEntry;
PFAT_DIR_ENTRY pDirEntry;
ASSERT(pFcb);
ASSERT(pFcb->parentFcb);
@@ -530,23 +668,23 @@ VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
Offset.u.HighPart = 0;
for (i = pFcb->startIndex; i <= pFcb->dirIndex; i++)
{
if (Context == NULL || ((i * sizeof(FATDirEntry)) % PAGE_SIZE) == 0)
if (Context == NULL || ((i * sizeof(FAT_DIR_ENTRY)) % PAGE_SIZE) == 0)
{
if (Context)
{
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
}
Offset.u.LowPart = (i * sizeof(FATDirEntry) / PAGE_SIZE) * PAGE_SIZE;
Offset.u.LowPart = (i * sizeof(FAT_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
&Context, (PVOID*)&pDirEntry);
}
pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))].Filename[0] = 0xe5;
pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))].Filename[0] = 0xe5;
if (i == pFcb->dirIndex)
{
CurrentCluster =
vfatDirEntryGetFirstCluster (DeviceExt,
&pDirEntry[i % (PAGE_SIZE / sizeof(FATDirEntry))]);
(PDIR_ENTRY)&pDirEntry[i % (PAGE_SIZE / sizeof(FAT_DIR_ENTRY))]);
}
}
if (Context)
@@ -565,4 +703,58 @@ VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
return STATUS_SUCCESS;
}
NTSTATUS
FATXDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
/*
* deleting an existing FAT entry
*/
{
ULONG CurrentCluster = 0, NextCluster;
PVOID Context = NULL;
LARGE_INTEGER Offset;
PFATX_DIR_ENTRY pDirEntry;
ULONG StartIndex;
ASSERT(pFcb);
ASSERT(pFcb->parentFcb);
ASSERT(pFcb->Flags & FCB_IS_FATX_ENTRY);
StartIndex = pFcb->startIndex;
DPRINT ("delEntry PathName \'%wZ\'\n", &pFcb->PathNameU);
DPRINT ("delete entry: %d\n", StartIndex);
Offset.u.HighPart = 0;
Offset.u.LowPart = (StartIndex * sizeof(FATX_DIR_ENTRY) / PAGE_SIZE) * PAGE_SIZE;
if (!CcMapData (pFcb->parentFcb->FileObject, &Offset, PAGE_SIZE, TRUE,
&Context, (PVOID*)&pDirEntry))
{
DPRINT1("CcMapData(Offset %x:%x, Length %d) failed\n", Offset.u.HighPart, Offset.u.LowPart, PAGE_SIZE);
return STATUS_UNSUCCESSFUL;
}
pDirEntry = &pDirEntry[StartIndex % (PAGE_SIZE / sizeof(FATX_DIR_ENTRY))];
pDirEntry->FilenameLength = 0xe5;
CurrentCluster = vfatDirEntryGetFirstCluster (DeviceExt,
(PDIR_ENTRY)pDirEntry);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
while (CurrentCluster && CurrentCluster != 0xffffffff)
{
GetNextCluster (DeviceExt, CurrentCluster, &NextCluster);
/* FIXME: check status */
WriteCluster(DeviceExt, CurrentCluster, 0);
CurrentCluster = NextCluster;
}
return STATUS_SUCCESS;
}
NTSTATUS
VfatDelEntry (PDEVICE_EXTENSION DeviceExt, PVFATFCB pFcb)
{
if (DeviceExt->Flags & VCB_IS_FATX)
return FATXDelEntry(DeviceExt, pFcb);
else
return FATDelEntry(DeviceExt, pFcb);
}
/* EOF */
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* $Id: fat.c,v 1.46 2004/08/05 02:48:18 navaraf Exp $
* $Id: fat.c,v 1.47 2004/12/05 16:31:50 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -459,7 +459,7 @@ CountAvailableClusters(PDEVICE_EXTENSION DeviceExt,
{
if (DeviceExt->FatInfo.FatType == FAT12)
Status = FAT12CountAvailableClusters(DeviceExt);
else if (DeviceExt->FatInfo.FatType == FAT16)
else if (DeviceExt->FatInfo.FatType == FAT16 || DeviceExt->FatInfo.FatType == FATX16)
Status = FAT16CountAvailableClusters(DeviceExt);
else
Status = FAT32CountAvailableClusters(DeviceExt);
@@ -641,7 +641,7 @@ GetNextCluster(PDEVICE_EXTENSION DeviceExt,
DeviceExt, CurrentCluster);
if (CurrentCluster == 0)
return(STATUS_UNSUCCESSFUL);
return(STATUS_INVALID_PARAMETER);
ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster);
+64 -32
View File
@@ -1,4 +1,4 @@
/* $Id: fcb.c,v 1.42 2004/11/06 13:44:57 ekohl Exp $
/* $Id: fcb.c,v 1.43 2004/12/05 16:31:51 gvg Exp $
*
*
* FILE: drivers/fs/vfat/fcb.c
@@ -8,6 +8,7 @@
* PROGRAMMER: Jason Filby ([email protected])
* Rex Jolliff ([email protected])
* Hartmut Birr
* Herve Poussineau ([email protected])
*/
/* ------------------------------------------------------- INCLUDES */
@@ -38,6 +39,7 @@ ULONG vfatNameHash(ULONG hash, PUNICODE_STRING NameU)
PWCHAR curr;
register WCHAR c;
ASSERT(NameU->Buffer[0] != L'.');
curr = NameU->Buffer;
last = NameU->Buffer + NameU->Length / sizeof(WCHAR);
@@ -93,7 +95,7 @@ vfatInitFcb(PVFATFCB Fcb, PUNICODE_STRING NameU)
}
PVFATFCB
vfatNewFCB(PUNICODE_STRING pFileNameU)
vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU)
{
PVFATFCB rcFCB;
@@ -104,8 +106,15 @@ vfatNewFCB(PUNICODE_STRING pFileNameU)
{
return NULL;
}
memset(rcFCB, 0, sizeof(VFATFCB));
RtlZeroMemory(rcFCB, sizeof(VFATFCB));
vfatInitFcb(rcFCB, pFileNameU);
if (pVCB->Flags & VCB_IS_FATX)
{
rcFCB->Flags |= FCB_IS_FATX_ENTRY;
rcFCB->Attributes = &rcFCB->entry.FatX.Attrib;
}
else
rcFCB->Attributes = &rcFCB->entry.Fat.Attrib;
rcFCB->Hash.Hash = vfatNameHash(0, &rcFCB->PathNameU);
rcFCB->Hash.self = rcFCB;
rcFCB->ShortHash.self = rcFCB;
@@ -138,7 +147,7 @@ vfatDestroyFCB(PVFATFCB pFCB)
BOOL
vfatFCBIsDirectory(PVFATFCB FCB)
{
return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY;
return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY;
}
BOOL
@@ -312,7 +321,7 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
memset (newCCB, 0, sizeof (VFATCCB));
RtlZeroMemory(newCCB, sizeof (VFATCCB));
fileObject->Flags |= FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
@@ -347,28 +356,39 @@ vfatMakeRootFCB(PDEVICE_EXTENSION pVCB)
RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\");
FCB = vfatNewFCB(&NameU);
memset(FCB->entry.Filename, ' ', 11);
FCB->ShortHash.Hash = FCB->Hash.Hash;
FCB->entry.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
FCB->entry.Attrib = FILE_ATTRIBUTE_DIRECTORY;
if (pVCB->FatInfo.FatType == FAT32)
FCB = vfatNewFCB(pVCB, &NameU);
if (FCB->Flags & FCB_IS_FATX_ENTRY)
{
CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster;
FCB->entry.FirstCluster = (unsigned short)(FirstCluster & 0xffff);
FCB->entry.FirstClusterHigh = (unsigned short)(FirstCluster >> 16);
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
Size += pVCB->FatInfo.BytesPerCluster;
Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE);
}
memset(FCB->entry.FatX.Filename, ' ', 42);
FCB->entry.FatX.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
FCB->entry.FatX.Attrib = FILE_ATTRIBUTE_DIRECTORY;
FCB->entry.FatX.FirstCluster = 1;
Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
}
else
{
FCB->entry.FirstCluster = 1;
Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
memset(FCB->entry.Fat.Filename, ' ', 11);
FCB->entry.Fat.FileSize = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
FCB->entry.Fat.Attrib = FILE_ATTRIBUTE_DIRECTORY;
if (pVCB->FatInfo.FatType == FAT32)
{
CurrentCluster = FirstCluster = pVCB->FatInfo.RootCluster;
FCB->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0xffff);
FCB->entry.Fat.FirstClusterHigh = (unsigned short)(FirstCluster >> 16);
while (CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
{
Size += pVCB->FatInfo.BytesPerCluster;
Status = NextCluster (pVCB, FirstCluster, &CurrentCluster, FALSE);
}
}
else
{
FCB->entry.Fat.FirstCluster = 1;
Size = pVCB->FatInfo.rootDirectorySectors * pVCB->FatInfo.BytesPerSector;
}
}
FCB->ShortHash.Hash = FCB->Hash.Hash;
FCB->RefCount = 2;
FCB->dirIndex = 0;
FCB->RFCB.FileSize.QuadPart = Size;
@@ -435,10 +455,18 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
RtlAppendUnicodeStringToString(&NameU, &DirContext->ShortNameU);
}
NameU.Buffer[NameU.Length / sizeof(WCHAR)] = 0;
rcFCB = vfatNewFCB (&NameU);
memcpy (&rcFCB->entry, &DirContext->FatDirEntry, sizeof (FAT_DIR_ENTRY));
rcFCB = vfatNewFCB (vcb, &NameU);
RtlCopyMemory (&rcFCB->entry, &DirContext->DirEntry, sizeof (DIR_ENTRY));
RtlCopyUnicodeString(&rcFCB->ShortNameU, &DirContext->ShortNameU);
rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
if (vcb->Flags & VCB_IS_FATX)
{
rcFCB->ShortHash.Hash = rcFCB->Hash.Hash;
}
else
{
rcFCB->ShortHash.Hash = vfatNameHash(hash, &rcFCB->ShortNameU);
}
if (vfatFCBIsDirectory(rcFCB))
{
@@ -450,7 +478,7 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
{
Size = vcb->FatInfo.rootDirectorySectors * vcb->FatInfo.BytesPerSector;
}
else
else if (FirstCluster != 0)
{
CurrentCluster = FirstCluster;
while (CurrentCluster != 0xffffffff)
@@ -460,9 +488,13 @@ vfatMakeFCBFromDirEntry(PVCB vcb,
}
}
}
else if (rcFCB->Flags & FCB_IS_FATX_ENTRY)
{
Size = rcFCB->entry.FatX.FileSize;
}
else
{
Size = rcFCB->entry.FileSize;
Size = rcFCB->entry.Fat.FileSize;
}
rcFCB->dirIndex = DirContext->DirIndex;
rcFCB->startIndex = DirContext->StartIndex;
@@ -494,7 +526,7 @@ vfatAttachFCBToFileObject (PDEVICE_EXTENSION vcb,
CHECKPOINT;
return STATUS_INSUFFICIENT_RESOURCES;
}
memset (newCCB, 0, sizeof (VFATCCB));
RtlZeroMemory (newCCB, sizeof (VFATCCB));
fileObject->Flags = fileObject->Flags | FO_FCB_IS_VALID |
FO_DIRECT_CACHE_PAGING_READ;
@@ -542,7 +574,7 @@ vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
while (TRUE)
{
status = vfatGetNextDirEntry(&Context,
status = pDeviceExt->GetNextDirEntry(&Context,
&Page,
pDirectoryFCB,
&DirContext,
@@ -562,7 +594,7 @@ vfatDirFindFile (PDEVICE_EXTENSION pDeviceExt,
&DirContext.LongNameU);
DirContext.LongNameU.Buffer[DirContext.LongNameU.Length / sizeof(WCHAR)] = 0;
DirContext.ShortNameU.Buffer[DirContext.ShortNameU.Length / sizeof(WCHAR)] = 0;
if (!ENTRY_VOLUME(&DirContext.FatDirEntry))
if (!ENTRY_VOLUME(pDeviceExt, &DirContext.DirEntry))
{
FoundLong = RtlEqualUnicodeString(FileToFindU, &DirContext.LongNameU, TRUE);
if (FoundLong == FALSE)
@@ -646,7 +678,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
curr = pFileNameU->Buffer + FCB->PathNameU.Length / sizeof(WCHAR);
last = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1;
}
memcpy(pFileNameU->Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
RtlCopyMemory(pFileNameU->Buffer, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
}
}
else
@@ -699,7 +731,7 @@ vfatGetFCBForFile (PDEVICE_EXTENSION pVCB,
curr = prev + parentFCB->LongNameU.Length / sizeof(WCHAR);
last = pFileNameU->Buffer + pFileNameU->Length / sizeof(WCHAR) - 1;
}
memcpy(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length);
RtlCopyMemory(prev, parentFCB->LongNameU.Buffer, parentFCB->LongNameU.Length);
}
curr++;
prev = curr;
+146 -82
View File
@@ -1,4 +1,4 @@
/* $Id: finfo.c,v 1.38 2004/11/06 13:44:57 ekohl Exp $
/* $Id: finfo.c,v 1.39 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -6,6 +6,7 @@
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby ([email protected])
* Hartmut Birr
* Herve Poussineau ([email protected])
*
*/
@@ -106,26 +107,47 @@ VfatSetBasicInformation(PFILE_OBJECT FileObject,
ASSERT(NULL != DeviceExt);
ASSERT(NULL != BasicInfo);
/* Check volume label bit */
ASSERT(0 == (FCB->entry.Attrib & 0x08));
ASSERT(0 == (*FCB->Attributes & 0x08));
FsdSystemTimeToDosDateTime(&BasicInfo->CreationTime,
&FCB->entry.CreationDate,
&FCB->entry.CreationTime);
FsdSystemTimeToDosDateTime(&BasicInfo->LastAccessTime,
&FCB->entry.AccessDate,
if (FCB->Flags & FCB_IS_FATX_ENTRY)
{
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->CreationTime,
&FCB->entry.FatX.CreationDate,
&FCB->entry.FatX.CreationTime);
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->LastAccessTime,
&FCB->entry.FatX.AccessDate,
&FCB->entry.FatX.AccessTime);
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->LastWriteTime,
&FCB->entry.FatX.UpdateDate,
&FCB->entry.FatX.UpdateTime);
}
else
{
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->CreationTime,
&FCB->entry.Fat.CreationDate,
&FCB->entry.Fat.CreationTime);
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->LastAccessTime,
&FCB->entry.Fat.AccessDate,
NULL);
FsdSystemTimeToDosDateTime(&BasicInfo->LastWriteTime,
&FCB->entry.UpdateDate,
&FCB->entry.UpdateTime);
FsdSystemTimeToDosDateTime(DeviceExt,
&BasicInfo->LastWriteTime,
&FCB->entry.Fat.UpdateDate,
&FCB->entry.Fat.UpdateTime);
}
FCB->entry.Attrib = (unsigned char)((FCB->entry.Attrib &
*FCB->Attributes = (unsigned char)((*FCB->Attributes &
(FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
(BasicInfo->FileAttributes &
(FILE_ATTRIBUTE_ARCHIVE |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_READONLY)));
DPRINT("Setting attributes 0x%02x\n", FCB->entry.Attrib);
DPRINT("Setting attributes 0x%02x\n", *FCB->Attributes);
VfatUpdateEntry(FCB);
@@ -139,23 +161,48 @@ VfatGetBasicInformation(PFILE_OBJECT FileObject,
PFILE_BASIC_INFORMATION BasicInfo,
PULONG BufferLength)
{
PDEVICE_EXTENSION DeviceExt;
DPRINT("VfatGetBasicInformation()\n");
DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
return STATUS_BUFFER_OVERFLOW;
FsdDosDateTimeToSystemTime(FCB->entry.CreationDate,
FCB->entry.CreationTime,
if (FCB->Flags & FCB_IS_FATX_ENTRY)
{
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.FatX.CreationDate,
FCB->entry.FatX.CreationTime,
&BasicInfo->CreationTime);
FsdDosDateTimeToSystemTime(FCB->entry.AccessDate,
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.FatX.AccessDate,
FCB->entry.FatX.AccessTime,
&BasicInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.FatX.UpdateDate,
FCB->entry.FatX.UpdateTime,
&BasicInfo->LastWriteTime);
BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
}
else
{
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.Fat.CreationDate,
FCB->entry.Fat.CreationTime,
&BasicInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.Fat.AccessDate,
0,
&BasicInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(FCB->entry.UpdateDate,
FCB->entry.UpdateTime,
FsdDosDateTimeToSystemTime(DeviceExt,
FCB->entry.Fat.UpdateDate,
FCB->entry.Fat.UpdateTime,
&BasicInfo->LastWriteTime);
BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
}
BasicInfo->FileAttributes = FCB->entry.Attrib & 0x3f;
BasicInfo->FileAttributes = *FCB->Attributes & 0x3f;
/* Synthesize FILE_ATTRIBUTE_NORMAL */
if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
FILE_ATTRIBUTE_ARCHIVE |
@@ -188,7 +235,7 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
ASSERT(FCB != NULL);
if (FCB->entry.Attrib & FILE_ATTRIBUTE_READONLY)
if (*FCB->Attributes & FILE_ATTRIBUTE_READONLY)
{
return STATUS_CANNOT_DELETE;
}
@@ -259,7 +306,7 @@ VfatGetNameInformation(PFILE_OBJECT FileObject,
return STATUS_BUFFER_OVERFLOW;
NameInfo->FileNameLength = FCB->PathNameU.Length;
memcpy(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);
NameInfo->FileName[FCB->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_NAME_INFORMATION) + FCB->PathNameU.Length + sizeof(WCHAR));
@@ -286,6 +333,7 @@ VfatGetInternalInformation(PVFATFCB Fcb,
static NTSTATUS
VfatGetNetworkOpenInformation(PVFATFCB Fcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
PULONG BufferLength)
/*
@@ -298,16 +346,38 @@ VfatGetNetworkOpenInformation(PVFATFCB Fcb,
if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
return(STATUS_BUFFER_OVERFLOW);
FsdDosDateTimeToSystemTime(Fcb->entry.CreationDate,
Fcb->entry.CreationTime,
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.FatX.CreationDate,
Fcb->entry.FatX.CreationTime,
&NetworkInfo->CreationTime);
FsdDosDateTimeToSystemTime(Fcb->entry.AccessDate,
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.FatX.AccessDate,
Fcb->entry.FatX.AccessTime,
&NetworkInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.FatX.UpdateDate,
Fcb->entry.FatX.UpdateTime,
&NetworkInfo->LastWriteTime);
NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
}
else
{
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.Fat.CreationDate,
Fcb->entry.Fat.CreationTime,
&NetworkInfo->CreationTime);
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.Fat.AccessDate,
0,
&NetworkInfo->LastAccessTime);
FsdDosDateTimeToSystemTime(Fcb->entry.UpdateDate,
Fcb->entry.UpdateTime,
FsdDosDateTimeToSystemTime(DeviceExt,
Fcb->entry.Fat.UpdateDate,
Fcb->entry.Fat.UpdateTime,
&NetworkInfo->LastWriteTime);
NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
}
if (vfatFCBIsDirectory(Fcb))
{
NetworkInfo->EndOfFile.QuadPart = 0L;
@@ -318,7 +388,7 @@ VfatGetNetworkOpenInformation(PVFATFCB Fcb,
NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
}
NetworkInfo->FileAttributes = Fcb->entry.Attrib & 0x3f;
NetworkInfo->FileAttributes = *Fcb->Attributes & 0x3f;
*BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
return STATUS_SUCCESS;
@@ -328,12 +398,16 @@ VfatGetNetworkOpenInformation(PVFATFCB Fcb,
static NTSTATUS
VfatGetAllInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
PDEVICE_OBJECT DeviceObject,
PFILE_ALL_INFORMATION Info,
PULONG BufferLength)
/*
* FUNCTION: Retrieve the all file information
*/
{
NTSTATUS Status;
ULONG InitialBufferLength = *BufferLength;
ASSERT(Info);
ASSERT(Fcb);
@@ -341,60 +415,28 @@ VfatGetAllInformation(PFILE_OBJECT FileObject,
return(STATUS_BUFFER_OVERFLOW);
/* Basic Information */
FsdDosDateTimeToSystemTime(Fcb->entry.CreationDate,
Fcb->entry.CreationTime,
&Info->BasicInformation.CreationTime);
FsdDosDateTimeToSystemTime(Fcb->entry.AccessDate,
0,
&Info->BasicInformation.LastAccessTime);
FsdDosDateTimeToSystemTime(Fcb->entry.UpdateDate,
Fcb->entry.UpdateTime,
&Info->BasicInformation.LastWriteTime);
Info->BasicInformation.ChangeTime.QuadPart = Info->BasicInformation.LastWriteTime.QuadPart;
Info->BasicInformation.FileAttributes = Fcb->entry.Attrib & 0x3f;
Status = VfatGetBasicInformation(FileObject, Fcb, DeviceObject, &Info->BasicInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Standard Information */
if (vfatFCBIsDirectory(Fcb))
{
Info->StandardInformation.AllocationSize.QuadPart = 0LL;
Info->StandardInformation.EndOfFile.QuadPart = 0LL;
Info->StandardInformation.Directory = TRUE;
}
else
{
Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize;
Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize;
Info->StandardInformation.Directory = FALSE;
}
Info->StandardInformation.NumberOfLinks = 0;
Info->StandardInformation.DeletePending = Fcb->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;
Status = VfatGetStandardInformation(Fcb, &Info->StandardInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Internal Information */
/* FIXME: get a real index, that can be used in a create operation */
Info->InternalInformation.IndexNumber.QuadPart = 0;
Status = VfatGetInternalInformation(Fcb, &Info->InternalInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* EA Information */
Info->EaInformation.EaSize = 0;
/* Access Information */
/* The IO-Manager adds this information */
/* Access Information: The IO-Manager adds this information */
/* Position Information */
Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart;
/* Mode Information */
/* The IO-Manager adds this information */
/* Alignment Information */
/* The IO-Manager adds this information */
Status = VfatGetPositionInformation(FileObject, Fcb, DeviceObject, &Info->PositionInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
/* Mode Information: The IO-Manager adds this information */
/* Alignment Information: The IO-Manager adds this information */
/* Name Information */
Info->NameInformation.FileNameLength = Fcb->PathNameU.Length;
RtlCopyMemory(Info->NameInformation.FileName, Fcb->PathNameU.Buffer, Fcb->PathNameU.Length);
Info->NameInformation.FileName[Fcb->PathNameU.Length / sizeof(WCHAR)] = 0;
*BufferLength -= (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
Status = VfatGetNameInformation(FileObject, Fcb, DeviceObject, &Info->NameInformation, BufferLength);
if (!NT_SUCCESS(Status)) return Status;
*BufferLength = InitialBufferLength - (sizeof(FILE_ALL_INFORMATION) + Fcb->PathNameU.Length + sizeof(WCHAR));
return STATUS_SUCCESS;
}
@@ -410,7 +452,10 @@ VOID UpdateFileSize(PFILE_OBJECT FileObject, PVFATFCB Fcb, ULONG Size, ULONG Clu
}
if (!vfatFCBIsDirectory(Fcb))
{
Fcb->entry.FileSize = Size;
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
Fcb->entry.FatX.FileSize = Size;
else
Fcb->entry.Fat.FileSize = Size;
}
Fcb->RFCB.FileSize.QuadPart = Size;
Fcb->RFCB.ValidDataLength.QuadPart = Size;
@@ -438,7 +483,10 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
DPRINT("VfatSetAllocationSizeInformation()\n");
OldSize = Fcb->entry.FileSize;
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
OldSize = Fcb->entry.FatX.FileSize;
else
OldSize = Fcb->entry.Fat.FileSize;
if (AllocationSize->u.HighPart > 0)
{
return STATUS_INVALID_PARAMETER;
@@ -482,8 +530,15 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
}
return STATUS_DISK_FULL;
}
Fcb->entry.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
Fcb->entry.FirstClusterHigh = (unsigned short)((FirstCluster & 0xFFFF0000) >> 16);
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
Fcb->entry.FatX.FirstCluster = FirstCluster;
}
else
{
Fcb->entry.Fat.FirstCluster = (unsigned short)(FirstCluster & 0x0000FFFF);
Fcb->entry.Fat.FirstClusterHigh = (unsigned short)((FirstCluster & 0xFFFF0000) >> 16);
}
}
else
{
@@ -547,8 +602,15 @@ VfatSetAllocationSizeInformation(PFILE_OBJECT FileObject,
}
else
{
Fcb->entry.FirstCluster = 0;
Fcb->entry.FirstClusterHigh = 0;
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
Fcb->entry.FatX.FirstCluster = 0;
}
else
{
Fcb->entry.Fat.FirstCluster = 0;
Fcb->entry.Fat.FirstClusterHigh = 0;
}
NCluster = Cluster = FirstCluster;
Status = STATUS_SUCCESS;
@@ -640,12 +702,14 @@ NTSTATUS VfatQueryInformation(PVFAT_IRP_CONTEXT IrpContext)
break;
case FileNetworkOpenInformation:
RC = VfatGetNetworkOpenInformation(FCB,
IrpContext->DeviceExt,
SystemBuffer,
&BufferLength);
break;
case FileAllInformation:
RC = VfatGetAllInformation(IrpContext->FileObject,
FCB,
IrpContext->DeviceObject,
SystemBuffer,
&BufferLength);
break;
+175 -81
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: fsctl.c,v 1.36 2004/11/06 13:44:57 ekohl Exp $
/* $Id: fsctl.c,v 1.37 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -55,6 +55,7 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
ULONG Sectors;
LARGE_INTEGER Offset;
struct _BootSector* Boot;
struct _BootSectorFatX* BootFatX;
BOOL PartitionInfoIsValid = FALSE;
DPRINT("VfatHasFileSystem\n");
@@ -92,17 +93,15 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
return Status;
}
PartitionInfoIsValid = TRUE;
#if defined(DBG) && !defined(NDEBUG)
DbgPrint("Partition Information:\n");
DbgPrint("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart / 512);
DbgPrint("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart / 512);
DbgPrint("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
DbgPrint("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
DbgPrint("PartitionType %u\n", PartitionInfo.PartitionType);
DbgPrint("BootIndicator %u\n", PartitionInfo.BootIndicator);
DbgPrint("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
DbgPrint("RewritePartition %u\n", PartitionInfo.RewritePartition);
#endif
DPRINT("Partition Information:\n");
DPRINT("StartingOffset %u\n", PartitionInfo.StartingOffset.QuadPart / 512);
DPRINT("PartitionLength %u\n", PartitionInfo.PartitionLength.QuadPart / 512);
DPRINT("HiddenSectors %u\n", PartitionInfo.HiddenSectors);
DPRINT("PartitionNumber %u\n", PartitionInfo.PartitionNumber);
DPRINT("PartitionType %u\n", PartitionInfo.PartitionType);
DPRINT("BootIndicator %u\n", PartitionInfo.BootIndicator);
DPRINT("RecognizedPartition %u\n", PartitionInfo.RecognizedPartition);
DPRINT("RewritePartition %u\n", PartitionInfo.RewritePartition);
if (PartitionInfo.PartitionType)
{
if (PartitionInfo.PartitionType == PARTITION_FAT_12 ||
@@ -151,20 +150,28 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
}
Offset.QuadPart = 0;
/* Try to recognize FAT12/FAT16/FAT32 partitions */
Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE);
if (NT_SUCCESS(Status))
{
if (Boot->Signatur1 != 0xaa55)
{
DPRINT1("Signature %04x\n", Boot->Signatur1);
BootFatX = (struct _BootSectorFatX *) Boot;
if (BootFatX->SysType[0] != 'F' ||
BootFatX->SysType[1] != 'A' ||
BootFatX->SysType[2] != 'T' ||
BootFatX->SysType[3] != 'X')
{
DPRINT1("Signature %04x\n", Boot->Signatur1);
}
*RecognizedFS=FALSE;
}
if (*RecognizedFS &&
Boot->BytesPerSector != 512 &&
Boot->BytesPerSector != 1024 &&
Boot->BytesPerSector != 512 &&
Boot->BytesPerSector != 1024 &&
Boot->BytesPerSector != 2048 &&
Boot->BytesPerSector != 4096)
Boot->BytesPerSector != 4096)
{
DPRINT1("BytesPerSector %d\n", Boot->BytesPerSector);
*RecognizedFS=FALSE;
@@ -172,7 +179,7 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
if (*RecognizedFS &&
Boot->FATCount != 1 &&
Boot->FATCount != 2)
Boot->FATCount != 2)
{
DPRINT1("FATCount %d\n", Boot->FATCount);
*RecognizedFS=FALSE;
@@ -180,28 +187,28 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
if (*RecognizedFS &&
Boot->Media != 0xf0 &&
Boot->Media != 0xf8 &&
Boot->Media != 0xf9 &&
Boot->Media != 0xfa &&
Boot->Media != 0xfb &&
Boot->Media != 0xfc &&
Boot->Media != 0xfd &&
Boot->Media != 0xfe &&
Boot->Media != 0xff)
Boot->Media != 0xf8 &&
Boot->Media != 0xf9 &&
Boot->Media != 0xfa &&
Boot->Media != 0xfb &&
Boot->Media != 0xfc &&
Boot->Media != 0xfd &&
Boot->Media != 0xfe &&
Boot->Media != 0xff)
{
DPRINT1("Media %02x\n", Boot->Media);
*RecognizedFS=FALSE;
}
if (*RecognizedFS &&
Boot->SectorsPerCluster != 1 &&
Boot->SectorsPerCluster != 2 &&
Boot->SectorsPerCluster != 1 &&
Boot->SectorsPerCluster != 2 &&
Boot->SectorsPerCluster != 4 &&
Boot->SectorsPerCluster != 8 &&
Boot->SectorsPerCluster != 8 &&
Boot->SectorsPerCluster != 16 &&
Boot->SectorsPerCluster != 32 &&
Boot->SectorsPerCluster != 32 &&
Boot->SectorsPerCluster != 64 &&
Boot->SectorsPerCluster != 128)
Boot->SectorsPerCluster != 128)
{
DPRINT1("SectorsPerCluster %02x\n", Boot->SectorsPerCluster);
*RecognizedFS=FALSE;
@@ -247,12 +254,12 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
DPRINT("FAT16\n");
FatInfo.FatType = FAT16;
}
if (PartitionInfoIsValid &&
FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
{
CHECKPOINT1;
*RecognizedFS = FALSE;
}
if (PartitionInfoIsValid &&
FatInfo.Sectors > PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector)
{
CHECKPOINT1;
*RecognizedFS = FALSE;
}
if (pFatInfo && *RecognizedFS)
{
@@ -262,6 +269,81 @@ VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
}
ExFreePool(Boot);
if (!*RecognizedFS && PartitionInfoIsValid)
{
BootFatX = ExAllocatePool(NonPagedPool, sizeof(struct _BootSectorFatX));
if (BootFatX == NULL)
{
*RecognizedFS=FALSE;
return STATUS_INSUFFICIENT_RESOURCES;
}
Offset.QuadPart = 0;
/* Try to recognize FATX16/FATX32 partitions (Xbox) */
Status = VfatReadDisk(DeviceToMount, &Offset, sizeof(struct _BootSectorFatX), (PUCHAR) BootFatX, FALSE);
if (NT_SUCCESS(Status))
{
*RecognizedFS = TRUE;
if (BootFatX->SysType[0] != 'F' ||
BootFatX->SysType[1] != 'A' ||
BootFatX->SysType[2] != 'T' ||
BootFatX->SysType[3] != 'X')
{
DPRINT1("SysType %c%c%c%c\n", BootFatX->SysType[0], BootFatX->SysType[1], BootFatX->SysType[2], BootFatX->SysType[3]);
*RecognizedFS=FALSE;
}
if (*RecognizedFS &&
BootFatX->SectorsPerCluster != 1 &&
BootFatX->SectorsPerCluster != 2 &&
BootFatX->SectorsPerCluster != 4 &&
BootFatX->SectorsPerCluster != 8 &&
BootFatX->SectorsPerCluster != 16 &&
BootFatX->SectorsPerCluster != 32 &&
BootFatX->SectorsPerCluster != 64 &&
BootFatX->SectorsPerCluster != 128)
{
DPRINT1("SectorsPerCluster %lu\n", BootFatX->SectorsPerCluster);
*RecognizedFS=FALSE;
}
if (*RecognizedFS)
{
FatInfo.BytesPerSector = DiskGeometry.BytesPerSector;
FatInfo.SectorsPerCluster = BootFatX->SectorsPerCluster;
FatInfo.rootDirectorySectors = BootFatX->SectorsPerCluster;
FatInfo.BytesPerCluster = BootFatX->SectorsPerCluster * DiskGeometry.BytesPerSector;
FatInfo.NumberOfClusters = PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerCluster;
if (FatInfo.NumberOfClusters < 65525)
{
DPRINT("FATX16\n");
FatInfo.FatType = FATX16;
}
else
{
DPRINT("FATX32\n");
FatInfo.FatType = FATX32;
}
FatInfo.VolumeID = BootFatX->VolumeID;
FatInfo.FATStart = sizeof(struct _BootSectorFatX) / DiskGeometry.BytesPerSector;
FatInfo.FATCount = BootFatX->FATCount;
FatInfo.FATSectors =
ROUND_UP(FatInfo.NumberOfClusters * (FatInfo.FatType == FATX16 ? 2 : 4), 4096) /
FatInfo.BytesPerSector;
FatInfo.rootStart = FatInfo.FATStart + FatInfo.FATCount * FatInfo.FATSectors;
FatInfo.dataStart = FatInfo.rootStart + FatInfo.rootDirectorySectors;
FatInfo.Sectors = PartitionInfo.PartitionLength.QuadPart / FatInfo.BytesPerSector;
if (pFatInfo && *RecognizedFS)
{
*pFatInfo = FatInfo;
}
}
}
ExFreePool(BootFatX);
}
DPRINT("VfatHasFileSystem done\n");
return Status;
}
@@ -357,31 +439,65 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
goto ByeBye;
}
#ifndef NDEBUG
DbgPrint("BytesPerSector: %d\n", DeviceExt->FatInfo.BytesPerSector);
DbgPrint("SectorsPerCluster: %d\n", DeviceExt->FatInfo.SectorsPerCluster);
DbgPrint("FATCount: %d\n", DeviceExt->FatInfo.FATCount);
DbgPrint("FATSectors: %d\n", DeviceExt->FatInfo.FATSectors);
DbgPrint("RootStart: %d\n", DeviceExt->FatInfo.rootStart);
DbgPrint("DataStart: %d\n", DeviceExt->FatInfo.dataStart);
DPRINT("BytesPerSector: %d\n", DeviceExt->FatInfo.BytesPerSector);
DPRINT("SectorsPerCluster: %d\n", DeviceExt->FatInfo.SectorsPerCluster);
DPRINT("FATCount: %d\n", DeviceExt->FatInfo.FATCount);
DPRINT("FATSectors: %d\n", DeviceExt->FatInfo.FATSectors);
DPRINT("RootStart: %d\n", DeviceExt->FatInfo.rootStart);
DPRINT("DataStart: %d\n", DeviceExt->FatInfo.dataStart);
if (DeviceExt->FatInfo.FatType == FAT32)
{
DbgPrint("RootCluster: %d\n", DeviceExt->FatInfo.RootCluster);
DPRINT("RootCluster: %d\n", DeviceExt->FatInfo.RootCluster);
}
#endif
DeviceExt->StorageDevice = DeviceToMount;
DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
switch (DeviceExt->FatInfo.FatType)
{
case FAT12:
DeviceExt->GetNextCluster = FAT12GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT12WriteCluster;
break;
DPRINT("FsDeviceObject %lx\n", DeviceObject);
case FAT16:
case FATX16:
DeviceExt->GetNextCluster = FAT16GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT16WriteCluster;
break;
case FAT32:
case FATX32:
DeviceExt->GetNextCluster = FAT32GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT32WriteCluster;
break;
}
if (DeviceExt->FatInfo.FatType == FATX16
|| DeviceExt->FatInfo.FatType == FATX32)
{
DeviceExt->Flags |= VCB_IS_FATX;
DeviceExt->GetNextDirEntry = FATXGetNextDirEntry;
DeviceExt->BaseDateYear = 2000;
}
else
{
DeviceExt->GetNextDirEntry = FATGetNextDirEntry;
DeviceExt->BaseDateYear = 1980;
}
DeviceExt->StorageDevice = DeviceToMount;
DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
DeviceObject->StackSize = DeviceExt->StorageDevice->StackSize + 1;
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DPRINT("FsDeviceObject %lx\n", DeviceObject);
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\$$Fat$$");
Fcb = vfatNewFCB(&NameU);
Fcb = vfatNewFCB(DeviceExt, &NameU);
if (Fcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -394,7 +510,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
goto ByeBye;
}
memset(Ccb, 0, sizeof (VFATCCB));
RtlZeroMemory(Ccb, sizeof (VFATCCB));
DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
DeviceExt->FATFileObject->FsContext = Fcb;
DeviceExt->FATFileObject->FsContext2 = Ccb;
@@ -403,7 +519,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
Fcb->FileObject = DeviceExt->FATFileObject;
Fcb->Flags = FCB_IS_FAT;
Fcb->Flags |= FCB_IS_FAT;
Fcb->RFCB.FileSize.QuadPart = DeviceExt->FatInfo.FATSectors * DeviceExt->FatInfo.BytesPerSector;
Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
@@ -419,38 +535,17 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
}
if (!NT_SUCCESS (Status))
{
DbgPrint ("CcRosInitializeFileCache failed\n");
DPRINT1 ("CcRosInitializeFileCache failed\n");
goto ByeBye;
}
DeviceExt->LastAvailableCluster = 2;
ExInitializeResourceLite(&DeviceExt->DirResource);
ExInitializeResourceLite(&DeviceExt->FatResource);
switch (DeviceExt->FatInfo.FatType)
{
case FAT12:
DeviceExt->GetNextCluster = FAT12GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT12FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT12WriteCluster;
break;
case FAT16:
DeviceExt->GetNextCluster = FAT16GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT16FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT16WriteCluster;
break;
case FAT32:
DeviceExt->GetNextCluster = FAT32GetNextCluster;
DeviceExt->FindAndMarkAvailableCluster = FAT32FindAndMarkAvailableCluster;
DeviceExt->WriteCluster = FAT32WriteCluster;
break;
}
InitializeListHead(&DeviceExt->FcbListHead);
RtlRosInitUnicodeStringFromLiteral(&NameU, L"\\$$Volume$$");
VolumeFcb = vfatNewFCB(&NameU);
VolumeFcb = vfatNewFCB(DeviceExt, &NameU);
if (VolumeFcb == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -471,7 +566,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
/* read volume label */
ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
Status = STATUS_SUCCESS;
ByeBye:
@@ -737,4 +832,3 @@ NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
VfatFreeIrpContext(IrpContext);
return (Status);
}
+2 -2
View File
@@ -1,4 +1,4 @@
/* $Id: misc.c,v 1.14 2004/11/06 13:44:57 ekohl Exp $
/* $Id: misc.c,v 1.15 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -41,7 +41,7 @@ NTSTATUS VfatLockControl(
goto Fail;
}
if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY)
{
Status = STATUS_INVALID_PARAMETER;
goto Fail;
+19 -7
View File
@@ -1,5 +1,5 @@
/* $Id: rw.c,v 1.71 2004/11/06 13:44:57 ekohl Exp $
/* $Id: rw.c,v 1.72 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -592,7 +592,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
/* fail if file is a directory and no paged read */
if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
@@ -821,7 +821,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
}
/* fail if file is a directory and no paged read */
if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
@@ -1020,14 +1020,26 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
{
if(!(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
if(!(*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
LARGE_INTEGER SystemTime;
// set dates and times
KeQuerySystemTime (&SystemTime);
FsdSystemTimeToDosDateTime (&SystemTime, &Fcb->entry.UpdateDate,
&Fcb->entry.UpdateTime);
Fcb->entry.AccessDate = Fcb->entry.UpdateDate;
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
&SystemTime, &Fcb->entry.FatX.UpdateDate,
&Fcb->entry.FatX.UpdateTime);
Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
}
else
{
FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
&SystemTime, &Fcb->entry.Fat.UpdateDate,
&Fcb->entry.Fat.UpdateTime);
Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
}
/* set date and times to dirty */
Fcb->Flags |= FCB_IS_DIRTY;
}
+3 -3
View File
@@ -1,4 +1,4 @@
/* $Id: shutdown.c,v 1.8 2003/10/11 17:51:56 hbirr Exp $
/* $Id: shutdown.c,v 1.9 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -48,9 +48,9 @@ VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Irp->IoStatus.Status = Status;
}
/* FIXME: Unmount the logical volume */
ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
}
ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
/* FIXME: Free all global acquired resources */
Status = Irp->IoStatus.Status;
+94 -17
View File
@@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.69 2004/11/06 13:44:57 ekohl Exp $ */
/* $Id: vfat.h,v 1.70 2004/12/05 16:31:51 gvg Exp $ */
#include <ddk/ntifs.h>
@@ -52,6 +52,16 @@ struct _BootSector32
unsigned short Signature1; // 510
} __attribute__((packed));
struct _BootSectorFatX
{
unsigned char SysType[4]; // 0
unsigned long VolumeID; // 4
unsigned long SectorsPerCluster; // 8
unsigned short FATCount; // 12
unsigned long Unknown; // 14
unsigned char Unused[4078]; // 18
} __attribute__((packed));
struct _FsInfoSector
{
unsigned long ExtBootSignature2; // 0
@@ -68,10 +78,22 @@ typedef struct _BootSector BootSector;
#define VFAT_CASE_LOWER_BASE 8 // base is lower case
#define VFAT_CASE_LOWER_EXT 16 // extension is lower case
#define ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
#define ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
#define ENTRY_DELETED(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_DELETED(&((DirEntry)->FatX)) : FAT_ENTRY_DELETED(&((DirEntry)->Fat)))
#define ENTRY_VOLUME(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_VOLUME(&((DirEntry)->FatX)) : FAT_ENTRY_VOLUME(&((DirEntry)->Fat)))
#define ENTRY_END(DeviceExt, DirEntry) ((DeviceExt)->Flags & VCB_IS_FATX ? FATX_ENTRY_END(&((DirEntry)->FatX)) : FAT_ENTRY_END(&((DirEntry)->Fat)))
#define FAT_ENTRY_DELETED(DirEntry) ((DirEntry)->Filename[0] == 0xe5)
#define FAT_ENTRY_END(DirEntry) ((DirEntry)->Filename[0] == 0)
#define FAT_ENTRY_LONG(DirEntry) (((DirEntry)->Attrib & 0x3f) == 0x0f)
#define FAT_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
#define FATX_ENTRY_DELETED(DirEntry) ((DirEntry)->FilenameLength == 0xe5)
#define FATX_ENTRY_END(DirEntry) ((DirEntry)->FilenameLength == 0xff)
#define FATX_ENTRY_LONG(DirEntry) (FALSE)
#define FATX_ENTRY_VOLUME(DirEntry) (((DirEntry)->Attrib & 0x1f) == 0x08)
#define FAT_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FAT_DIR_ENTRY))
#define FATX_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof (FATX_DIR_ENTRY))
struct _FATDirEntry
{
@@ -87,7 +109,32 @@ struct _FATDirEntry
unsigned long FileSize;
} __attribute__((packed));
typedef struct _FATDirEntry FATDirEntry, FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
typedef struct _FATDirEntry FAT_DIR_ENTRY, *PFAT_DIR_ENTRY;
struct _FATXDirEntry
{
unsigned char FilenameLength; // 0
unsigned char Attrib; // 1
unsigned char Filename[42]; // 2
unsigned long FirstCluster; // 44
unsigned long FileSize; // 48
unsigned short UpdateTime; // 52
unsigned short UpdateDate; // 54
unsigned short CreationTime; // 56
unsigned short CreationDate; // 58
unsigned short AccessTime; // 60
unsigned short AccessDate; // 62
} __attribute__((packed));
typedef struct _FATXDirEntry FATX_DIR_ENTRY, *PFATX_DIR_ENTRY;
union _DIR_ENTRY
{
FAT_DIR_ENTRY Fat;
FATX_DIR_ENTRY FatX;
};
typedef union _DIR_ENTRY DIR_ENTRY, *PDIR_ENTRY;
struct _slot
{
@@ -106,12 +153,15 @@ typedef struct _slot slot;
#define BLOCKSIZE 512
#define FAT16 (1)
#define FAT12 (2)
#define FAT32 (3)
#define FAT16 (1)
#define FAT12 (2)
#define FAT32 (3)
#define FATX16 (4)
#define FATX32 (5)
#define VCB_VOLUME_LOCKED 0x0001
#define VCB_DISMOUNT_PENDING 0x0002
#define VCB_IS_FATX 0x0004
typedef struct
{
@@ -133,6 +183,7 @@ typedef struct
} FATINFO, *PFATINFO;
struct _VFATFCB;
struct _VFAT_DIRENTRY_CONTEXT;
typedef struct _HASHENTRY
{
@@ -150,6 +201,8 @@ typedef NTSTATUS (*PGET_NEXT_CLUSTER)(PDEVICE_EXTENSION,ULONG,PULONG);
typedef NTSTATUS (*PFIND_AND_MARK_AVAILABLE_CLUSTER)(PDEVICE_EXTENSION,PULONG);
typedef NTSTATUS (*PWRITE_CLUSTER)(PDEVICE_EXTENSION,ULONG,ULONG,PULONG);
typedef NTSTATUS (*PGET_NEXT_DIR_ENTRY)(PVOID*,PVOID*,struct _VFATFCB*,struct _VFAT_DIRENTRY_CONTEXT*,BOOLEAN);
typedef struct DEVICE_EXTENSION
{
ERESOURCE DirResource;
@@ -172,6 +225,11 @@ typedef struct DEVICE_EXTENSION
PGET_NEXT_CLUSTER GetNextCluster;
PFIND_AND_MARK_AVAILABLE_CLUSTER FindAndMarkAvailableCluster;
PWRITE_CLUSTER WriteCluster;
/* Pointers to functions for manipulating directory entries. */
PGET_NEXT_DIR_ENTRY GetNextDirEntry;
ULONG BaseDateYear;
LIST_ENTRY VolumeListEntry;
} DEVICE_EXTENSION, VCB, *PVCB;
@@ -195,7 +253,8 @@ extern PVFAT_GLOBAL_DATA VfatGlobalData;
#define FCB_IS_FAT 0x0004
#define FCB_IS_PAGE_FILE 0x0008
#define FCB_IS_VOLUME 0x0010
#define FCB_IS_DIRTY 0x0020
#define FCB_IS_DIRTY 0x0020
#define FCB_IS_FATX_ENTRY 0x0040
typedef struct _VFATFCB
{
@@ -207,7 +266,10 @@ typedef struct _VFATFCB
/* end FCB header required by ROS/NT */
/* directory entry for this file or directory */
FATDirEntry entry;
DIR_ENTRY entry;
/* Pointer to attributes in entry */
PUCHAR Attributes;
/* long file name, points into PathNameBuffer */
UNICODE_STRING LongNameU;
@@ -330,7 +392,7 @@ typedef struct _VFAT_DIRENTRY_CONTEXT
{
ULONG StartIndex;
ULONG DirIndex;
FAT_DIR_ENTRY FatDirEntry;
DIR_ENTRY DirEntry;
UNICODE_STRING LongNameU;
UNICODE_STRING ShortNameU;
} VFAT_DIRENTRY_CONTEXT, *PVFAT_DIRENTRY_CONTEXT;
@@ -379,11 +441,13 @@ NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
NTSTATUS VfatDirectoryControl (PVFAT_IRP_CONTEXT);
BOOL FsdDosDateTimeToSystemTime (WORD wDosDate,
BOOL FsdDosDateTimeToSystemTime (PDEVICE_EXTENSION DeviceExt,
WORD wDosDate,
WORD wDosTime,
PLARGE_INTEGER SystemTime);
BOOL FsdSystemTimeToDosDateTime (PLARGE_INTEGER SystemTime,
BOOL FsdSystemTimeToDosDateTime (PDEVICE_EXTENSION DeviceExt,
PLARGE_INTEGER SystemTime,
WORD *pwDosDate,
WORD *pwDosTime);
@@ -451,6 +515,12 @@ NTSTATUS VfatUpdateEntry (PVFATFCB pFcb);
NTSTATUS VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB);
BOOLEAN
vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt,
PVFATFCB pDirFcb,
ULONG nbSlots,
PULONG start);
/* -------------------------------------------------------- string.c */
VOID
@@ -529,11 +599,17 @@ WriteCluster(PDEVICE_EXTENSION DeviceExt,
/* ------------------------------------------------------ direntry.c */
ULONG vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PFAT_DIR_ENTRY pDirEntry);
PDIR_ENTRY pDirEntry);
BOOL VfatIsDirectoryEmpty(PVFATFCB Fcb);
NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
NTSTATUS FATGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First);
NTSTATUS FATXGetNextDirEntry(PVOID * pContext,
PVOID * pPage,
IN PVFATFCB pDirFcb,
IN PVFAT_DIRENTRY_CONTEXT DirContext,
@@ -541,7 +617,8 @@ NTSTATUS vfatGetNextDirEntry(PVOID * pContext,
/* ----------------------------------------------------------- fcb.c */
PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU);
PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB,
PUNICODE_STRING pFileNameU);
VOID vfatDestroyFCB (PVFATFCB pFCB);
+141 -9
View File
@@ -1,4 +1,4 @@
/* $Id: volume.c,v 1.27 2004/11/06 13:44:57 ekohl Exp $
/* $Id: volume.c,v 1.28 2004/12/05 16:31:51 gvg Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@@ -6,6 +6,7 @@
* PURPOSE: VFAT Filesystem
* PROGRAMMER: Jason Filby ([email protected])
* Hartmut Birr
* Herve Poussineau ([email protected])
*/
/* INCLUDES *****************************************************************/
@@ -42,7 +43,7 @@ FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
/* valid entries */
FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
memcpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel, FsVolumeInfo->VolumeLabelLength);
RtlCopyMemory(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel, FsVolumeInfo->VolumeLabelLength);
/* dummy entries */
FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
@@ -94,7 +95,7 @@ FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
FsAttributeInfo->FileSystemNameLength = Length;
memcpy(FsAttributeInfo->FileSystemName, pName, Length );
RtlCopyMemory(FsAttributeInfo->FileSystemName, pName, Length );
DPRINT("Finished FsdGetFsAttributeInformation()\n");
@@ -162,9 +163,140 @@ static NTSTATUS
FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
PFILE_FS_LABEL_INFORMATION FsLabelInfo)
{
PDEVICE_EXTENSION DeviceExt;
PVOID Context = NULL;
ULONG DirIndex = 0;
PDIR_ENTRY Entry;
PVFATFCB pRootFcb;
LARGE_INTEGER FileOffset;
BOOL LabelFound = FALSE;
DIR_ENTRY VolumeLabelDirEntry;
ULONG VolumeLabelDirIndex;
ULONG LabelLen;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
OEM_STRING StringO;
UNICODE_STRING StringW;
CHAR cString[43];
ULONG SizeDirEntry;
ULONG EntriesPerPage;
DPRINT("FsdSetFsLabelInformation()\n");
return(STATUS_NOT_IMPLEMENTED);
DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (sizeof(DeviceObject->Vpb->VolumeLabel) < FsLabelInfo->VolumeLabelLength)
{
CHECKPOINT;
return STATUS_NAME_TOO_LONG;
}
if (DeviceExt->Flags & VCB_IS_FATX)
{
if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 42)
return STATUS_NAME_TOO_LONG;
SizeDirEntry = sizeof(FATX_DIR_ENTRY);
EntriesPerPage = FATX_ENTRIES_PER_PAGE;
}
else
{
if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 11)
return STATUS_NAME_TOO_LONG;
SizeDirEntry = sizeof(FAT_DIR_ENTRY);
EntriesPerPage = FAT_ENTRIES_PER_PAGE;
}
/* Create Volume label dir entry */
LabelLen = FsLabelInfo->VolumeLabelLength / sizeof(WCHAR);
RtlZeroMemory(&VolumeLabelDirEntry, SizeDirEntry);
StringW.Buffer = FsLabelInfo->VolumeLabel;
StringW.Length = StringW.MaximumLength = FsLabelInfo->VolumeLabelLength;
StringO.Buffer = cString;
StringO.Length = 0;
StringO.MaximumLength = 42;
Status = RtlUnicodeStringToOemString(&StringO, &StringW, FALSE);
if (!NT_SUCCESS(Status))
return Status;
if (DeviceExt->Flags & VCB_IS_FATX)
{
RtlCopyMemory(VolumeLabelDirEntry.FatX.Filename, cString, LabelLen);
memset(&VolumeLabelDirEntry.FatX.Filename[LabelLen], ' ', 42 - LabelLen);
VolumeLabelDirEntry.FatX.Attrib = 0x08;
}
else
{
RtlCopyMemory(VolumeLabelDirEntry.Fat.Filename, cString, LabelLen);
memset(&VolumeLabelDirEntry.Fat.Filename[LabelLen], ' ', 11 - LabelLen);
VolumeLabelDirEntry.Fat.Attrib = 0x08;
}
pRootFcb = vfatOpenRootFCB(DeviceExt);
/* Search existing volume entry on disk */
FileOffset.QuadPart = 0;
if (CcMapData(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
{
while (TRUE)
{
if (ENTRY_VOLUME(DeviceExt, Entry))
{
/* Update entry */
LabelFound = TRUE;
RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
CcSetDirtyPinnedData(Context, NULL);
Status = STATUS_SUCCESS;
break;
}
if (ENTRY_END(DeviceExt, Entry))
{
break;
}
DirIndex++;
Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
if ((DirIndex % EntriesPerPage) == 0)
{
CcUnpinData(Context);
FileOffset.u.LowPart += PAGE_SIZE;
if (!CcMapData(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
{
Context = NULL;
break;
}
}
}
if (Context)
{
CcUnpinData(Context);
}
}
if (!LabelFound)
{
/* Add new entry for label */
if (!vfatFindDirSpace(DeviceExt, pRootFcb, 1, &VolumeLabelDirIndex))
Status = STATUS_DISK_FULL;
else
{
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry;
CcMapData(pRootFcb->FileObject, &FileOffset, SizeDirEntry,
TRUE, &Context, (PVOID*)&Entry);
RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
CcSetDirtyPinnedData(Context, NULL);
CcUnpinData(Context);
Status = STATUS_SUCCESS;
}
}
vfatReleaseFCB(DeviceExt, pRootFcb);
if (!NT_SUCCESS(Status))
{
return Status;
}
/* Update volume label in memory */
DeviceObject->Vpb->VolumeLabelLength = FsLabelInfo->VolumeLabelLength;
RtlCopyMemory(DeviceObject->Vpb->VolumeLabel, FsLabelInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabelLength);
return Status;
}
@@ -255,7 +387,7 @@ NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
/* PRECONDITION */
ASSERT(IrpContext);
DPRINT1("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext);
DPRINT ("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext);
if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
@@ -267,9 +399,9 @@ NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
BufferLength = Stack->Parameters.SetVolume.Length;
SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
DPRINT1("FsInformationClass %d\n", FsInformationClass);
DPRINT1("BufferLength %d\n", BufferLength);
DPRINT1("SystemBuffer %x\n", SystemBuffer);
DPRINT ("FsInformationClass %d\n", FsInformationClass);
DPRINT ("BufferLength %d\n", BufferLength);
DPRINT ("SystemBuffer %x\n", SystemBuffer);
switch(FsInformationClass)
{