? drivers/fs/vfat/compile.bat Index: drivers/fs/vfat/cleanup.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/cleanup.c,v retrieving revision 1.15 diff -u -r1.15 cleanup.c --- drivers/fs/vfat/cleanup.c 28 Aug 2004 22:19:12 -0000 1.15 +++ drivers/fs/vfat/cleanup.c 16 Nov 2004 00:28:24 -0000 @@ -35,7 +35,7 @@ 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 */ Index: drivers/fs/vfat/create.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/create.c,v retrieving revision 1.75 diff -u -r1.75 create.c --- drivers/fs/vfat/create.c 6 Nov 2004 13:44:56 -0000 1.75 +++ drivers/fs/vfat/create.c 18 Nov 2004 21:08:17 -0000 @@ -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 @@ 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ * 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); Index: drivers/fs/vfat/dir.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/dir.c,v retrieving revision 1.35 diff -u -r1.35 dir.c --- drivers/fs/vfat/dir.c 6 Nov 2004 13:44:57 -0000 1.35 +++ drivers/fs/vfat/dir.c 16 Nov 2004 15:24:41 -0000 @@ -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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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, + 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->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 (DirContext->FatDirEntry.UpdateDate, - DirContext->FatDirEntry.UpdateTime, + 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->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.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 @@ { 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; } Index: drivers/fs/vfat/direntry.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/direntry.c,v retrieving revision 1.17 diff -u -r1.17 direntry.c --- drivers/fs/vfat/direntry.c 1 Aug 2004 21:57:17 -0000 1.17 +++ drivers/fs/vfat/direntry.c 18 Nov 2004 20:57:25 -0000 @@ -8,6 +8,7 @@ * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * Rex Jolliff (rex@lvcablemodem.com) * Hartmut Birr + * Herve Poussineau (reactos@poussine.freesurf.fr) */ /* ------------------------------------------------------- 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 @@ 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 @@ { 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 @@ 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 @@ ULONG dirMap; PWCHAR pName; LARGE_INTEGER FileOffset; - FATDirEntry * fatDirEntry; + PFAT_DIR_ENTRY fatDirEntry; slot * longNameEntry; ULONG index; @@ -116,9 +173,9 @@ 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 @@ } - 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 @@ * 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 @@ *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 @@ } } - 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 @@ *pContext = NULL; return STATUS_NO_MORE_ENTRIES; } - fatDirEntry = (FATDirEntry*)*pPage; + fatDirEntry = (PFAT_DIR_ENTRY)*pPage; longNameEntry = (slot*) *pPage; } else @@ -199,14 +256,14 @@ 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 @@ } 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 @@ 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 @@ 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 @@ *pContext = NULL; return STATUS_NO_MORE_ENTRIES; } - fatDirEntry = (FATDirEntry*)*pPage; + fatDirEntry = (PFAT_DIR_ENTRY)*pPage; longNameEntry = (slot*) *pPage; } else @@ -290,10 +347,116 @@ } } 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; +} Index: drivers/fs/vfat/dirwr.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/dirwr.c,v retrieving revision 1.42 diff -u -r1.42 dirwr.c --- drivers/fs/vfat/dirwr.c 6 Nov 2004 13:44:57 -0000 1.42 +++ drivers/fs/vfat/dirwr.c 18 Nov 2004 21:13:04 -0000 @@ -26,21 +26,34 @@ */ { 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 @@ */ 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 @@ 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 @@ // 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 @@ 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 @@ } NTSTATUS -VfatAddEntry (PDEVICE_EXTENSION DeviceExt, +FATAddEntry (PDEVICE_EXTENSION DeviceExt, PUNICODE_STRING PathNameU, PFILE_OBJECT pFileObject, ULONG RequestedOptions, @@ -166,7 +192,7 @@ */ { PVOID Context = NULL; - FATDirEntry *pFatEntry; + PFAT_DIR_ENTRY pFatEntry; slot *pSlots; short nbSlots = 0, j, posCar; PUCHAR Buffer; @@ -180,7 +206,7 @@ ULONG size; long i; - ANSI_STRING NameA; + OEM_STRING NameA; CHAR aName[13]; BOOLEAN IsNameLegal; BOOLEAN SpacesFound; @@ -212,8 +238,8 @@ 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 @@ 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 @@ 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 @@ ExReleaseResourceLite(&pDirFcb->MainResource); vfatReleaseFCB(DeviceExt, pDirFcb); ExFreePool (Buffer); - CHECKPOINT; + CHECKPOINT; return STATUS_UNSUCCESSFUL; } IsNameLegal = RtlIsNameLegalDOS8Dot3(&DirContext.ShortNameU, &NameA, &SpacesFound); @@ -310,27 +336,27 @@ } 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 @@ 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 @@ { 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 @@ 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 @@ } 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 @@ 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 @@ /* 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 @@ } 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 @@ 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 @@ 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 @@ 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 */ Index: drivers/fs/vfat/fat.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/fat.c,v retrieving revision 1.46 diff -u -r1.46 fat.c --- drivers/fs/vfat/fat.c 5 Aug 2004 02:48:18 -0000 1.46 +++ drivers/fs/vfat/fat.c 22 Nov 2004 10:15:44 -0000 @@ -459,7 +459,7 @@ { 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 @@ DeviceExt, CurrentCluster); if (CurrentCluster == 0) - return(STATUS_UNSUCCESSFUL); + return(STATUS_INVALID_PARAMETER); ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE); Status = DeviceExt->GetNextCluster(DeviceExt, CurrentCluster, NextCluster); Index: drivers/fs/vfat/fcb.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/fcb.c,v retrieving revision 1.42 diff -u -r1.42 fcb.c --- drivers/fs/vfat/fcb.c 6 Nov 2004 13:44:57 -0000 1.42 +++ drivers/fs/vfat/fcb.c 16 Nov 2004 00:28:24 -0000 @@ -8,6 +8,7 @@ * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * Rex Jolliff (rex@lvcablemodem.com) * Hartmut Birr + * Herve Poussineau (reactos@poussine.freesurf.fr) */ /* ------------------------------------------------------- INCLUDES */ @@ -38,6 +39,7 @@ PWCHAR curr; register WCHAR c; + ASSERT(NameU->Buffer[0] != L'.'); curr = NameU->Buffer; last = NameU->Buffer + NameU->Length / sizeof(WCHAR); @@ -93,7 +95,7 @@ } PVFATFCB -vfatNewFCB(PUNICODE_STRING pFileNameU) +vfatNewFCB(PDEVICE_EXTENSION pVCB, PUNICODE_STRING pFileNameU) { PVFATFCB rcFCB; @@ -104,8 +106,15 @@ { 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 @@ BOOL vfatFCBIsDirectory(PVFATFCB FCB) { - return FCB->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY; + return *FCB->Attributes & FILE_ATTRIBUTE_DIRECTORY; } BOOL @@ -312,7 +321,7 @@ { 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 @@ 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) - { - 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); - } + FCB = vfatNewFCB(pVCB, &NameU); + if (FCB->Flags & FCB_IS_FATX_ENTRY) + { + 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 @@ 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 @@ { Size = vcb->FatInfo.rootDirectorySectors * vcb->FatInfo.BytesPerSector; } - else + else if (FirstCluster != 0) { CurrentCluster = FirstCluster; while (CurrentCluster != 0xffffffff) @@ -460,9 +488,13 @@ } } } + 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 @@ 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 @@ while (TRUE) { - status = vfatGetNextDirEntry(&Context, + status = pDeviceExt->GetNextDirEntry(&Context, &Page, pDirectoryFCB, &DirContext, @@ -562,7 +594,7 @@ &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 @@ 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 @@ 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; Index: drivers/fs/vfat/finfo.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/finfo.c,v retrieving revision 1.38 diff -u -r1.38 finfo.c --- drivers/fs/vfat/finfo.c 6 Nov 2004 13:44:57 -0000 1.38 +++ drivers/fs/vfat/finfo.c 16 Nov 2004 15:16:55 -0000 @@ -6,6 +6,7 @@ * PURPOSE: VFAT Filesystem * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * Hartmut Birr + * Herve Poussineau (reactos@poussine.freesurf.fr) * */ @@ -106,26 +107,47 @@ 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 @@ 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 @@ 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 @@ 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 @@ static NTSTATUS VfatGetNetworkOpenInformation(PVFATFCB Fcb, + PDEVICE_EXTENSION DeviceExt, PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, PULONG BufferLength) /* @@ -298,16 +346,38 @@ 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(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(Fcb->entry.AccessDate, + 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ } 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 @@ break; case FileNetworkOpenInformation: RC = VfatGetNetworkOpenInformation(FCB, + IrpContext->DeviceExt, SystemBuffer, &BufferLength); break; case FileAllInformation: RC = VfatGetAllInformation(IrpContext->FileObject, FCB, + IrpContext->DeviceObject, SystemBuffer, &BufferLength); break; Index: drivers/fs/vfat/fsctl.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/fsctl.c,v retrieving revision 1.36 diff -u -r1.36 fsctl.c --- drivers/fs/vfat/fsctl.c 6 Nov 2004 13:44:57 -0000 1.36 +++ drivers/fs/vfat/fsctl.c 22 Nov 2004 20:28:20 -0000 @@ -55,6 +55,7 @@ ULONG Sectors; LARGE_INTEGER Offset; struct _BootSector* Boot; + struct _BootSectorFatX* BootFatX; BOOL PartitionInfoIsValid = FALSE; DPRINT("VfatHasFileSystem\n"); @@ -151,7 +152,8 @@ } Offset.QuadPart = 0; - + + /* Try to recognize FAT12/FAT16/FAT32 partitions */ Status = VfatReadDisk(DeviceToMount, &Offset, DiskGeometry.BytesPerSector, (PUCHAR) Boot, FALSE); if (NT_SUCCESS(Status)) { @@ -161,10 +163,10 @@ *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 +174,7 @@ if (*RecognizedFS && Boot->FATCount != 1 && - Boot->FATCount != 2) + Boot->FATCount != 2) { DPRINT1("FATCount %d\n", Boot->FATCount); *RecognizedFS=FALSE; @@ -180,28 +182,28 @@ 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 +249,12 @@ 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 +264,83 @@ } 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 = (( + (FatInfo.NumberOfClusters * (FatInfo.FatType == FATX16 ? 2 : 4) + FatInfo.BytesPerCluster - 1) + / FatInfo.BytesPerCluster) + * FatInfo.BytesPerCluster) + / 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; } @@ -370,18 +449,54 @@ } #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 +509,7 @@ 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 +518,7 @@ 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; @@ -426,31 +541,10 @@ 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 +565,7 @@ /* read volume label */ ReadVolumeLabel(DeviceExt, DeviceObject->Vpb); - + Status = STATUS_SUCCESS; ByeBye: @@ -737,4 +831,3 @@ VfatFreeIrpContext(IrpContext); return (Status); } - Index: drivers/fs/vfat/misc.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/misc.c,v retrieving revision 1.14 diff -u -r1.14 misc.c --- drivers/fs/vfat/misc.c 6 Nov 2004 13:44:57 -0000 1.14 +++ drivers/fs/vfat/misc.c 16 Nov 2004 00:28:24 -0000 @@ -41,7 +41,7 @@ goto Fail; } - if (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY) + if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY) { Status = STATUS_INVALID_PARAMETER; goto Fail; Index: drivers/fs/vfat/rw.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/rw.c,v retrieving revision 1.71 diff -u -r1.71 rw.c --- drivers/fs/vfat/rw.c 6 Nov 2004 13:44:57 -0000 1.71 +++ drivers/fs/vfat/rw.c 16 Nov 2004 15:18:00 -0000 @@ -592,7 +592,7 @@ 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 @@ } /* 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 @@ 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; } Index: drivers/fs/vfat/shutdown.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/shutdown.c,v retrieving revision 1.8 diff -u -r1.8 shutdown.c --- drivers/fs/vfat/shutdown.c 11 Oct 2003 17:51:56 -0000 1.8 +++ drivers/fs/vfat/shutdown.c 21 Nov 2004 20:31:48 -0000 @@ -48,9 +48,9 @@ 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; Index: drivers/fs/vfat/vfat.h =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/vfat.h,v retrieving revision 1.69 diff -u -r1.69 vfat.h --- drivers/fs/vfat/vfat.h 6 Nov 2004 13:44:57 -0000 1.69 +++ drivers/fs/vfat/vfat.h 16 Nov 2004 15:23:16 -0000 @@ -52,6 +52,16 @@ 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 @@ #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 @@ 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 @@ #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 @@ } FATINFO, *PFATINFO; struct _VFATFCB; +struct _VFAT_DIRENTRY_CONTEXT; typedef struct _HASHENTRY { @@ -150,6 +201,8 @@ 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 @@ 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 @@ #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 @@ /* 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 @@ { 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 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 VfatDelEntry(PDEVICE_EXTENSION, PVFATFCB); +BOOLEAN +vfatFindDirSpace(PDEVICE_EXTENSION DeviceExt, + PVFATFCB pDirFcb, + ULONG nbSlots, + PULONG start); + /* -------------------------------------------------------- string.c */ VOID @@ -529,11 +599,17 @@ /* ------------------------------------------------------ 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 @@ /* ----------------------------------------------------------- fcb.c */ -PVFATFCB vfatNewFCB (PUNICODE_STRING pFileNameU); +PVFATFCB vfatNewFCB (PDEVICE_EXTENSION pVCB, + PUNICODE_STRING pFileNameU); VOID vfatDestroyFCB (PVFATFCB pFCB); Index: drivers/fs/vfat/volume.c =================================================================== RCS file: /CVS/ReactOS/reactos/drivers/fs/vfat/volume.c,v retrieving revision 1.27 diff -u -r1.27 volume.c --- drivers/fs/vfat/volume.c 6 Nov 2004 13:44:57 -0000 1.27 +++ drivers/fs/vfat/volume.c 18 Nov 2004 20:57:09 -0000 @@ -6,6 +6,7 @@ * PURPOSE: VFAT Filesystem * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * Hartmut Birr + * Herve Poussineau (reactos@poussine.freesurf.fr) */ /* INCLUDES *****************************************************************/ @@ -42,7 +43,7 @@ /* 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 @@ FsAttributeInfo->FileSystemNameLength = Length; - memcpy(FsAttributeInfo->FileSystemName, pName, Length ); + RtlCopyMemory(FsAttributeInfo->FileSystemName, pName, Length ); DPRINT("Finished FsdGetFsAttributeInformation()\n"); @@ -162,9 +163,140 @@ 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 @@ /* 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 @@ 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) {