/* ------------------------------------------------------- INCLUDES */
-#define NDEBUG
#include "vfat.h"
+#define NDEBUG
+#include <debug.h>
+
ULONG
-vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
- PDIR_ENTRY pFatDirEntry)
+vfatDirEntryGetFirstCluster(
+ PDEVICE_EXTENSION pDeviceExt,
+ PDIR_ENTRY pFatDirEntry)
{
ULONG cluster;
static
BOOLEAN
-FATIsDirectoryEmpty(PVFATFCB Fcb)
+FATIsDirectoryEmpty(
+ PVFATFCB Fcb)
{
LARGE_INTEGER FileOffset;
PVOID Context = NULL;
static
BOOLEAN
-FATXIsDirectoryEmpty(PVFATFCB Fcb)
+FATXIsDirectoryEmpty(
+ PVFATFCB Fcb)
{
LARGE_INTEGER FileOffset;
PVOID Context = NULL;
}
BOOLEAN
-VfatIsDirectoryEmpty(PVFATFCB Fcb)
+VfatIsDirectoryEmpty(
+ PVFATFCB Fcb)
{
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
return FATXIsDirectoryEmpty(Fcb);
}
NTSTATUS
-FATGetNextDirEntry(PVOID *pContext,
- PVOID *pPage,
- IN PVFATFCB pDirFcb,
- PVFAT_DIRENTRY_CONTEXT DirContext,
- BOOLEAN First)
+FATGetNextDirEntry(
+ PVOID *pContext,
+ PVOID *pPage,
+ IN PVFATFCB pDirFcb,
+ PVFAT_DIRENTRY_CONTEXT DirContext,
+ BOOLEAN First)
{
ULONG dirMap;
PWCHAR pName;
BOOLEAN Valid = TRUE;
BOOLEAN Back = FALSE;
- DirContext->LongNameU.Buffer[0] = 0;
+ DirContext->LongNameU.Length = 0;
+ DirContext->LongNameU.Buffer[0] = UNICODE_NULL;
FileOffset.u.HighPart = 0;
FileOffset.u.LowPart = ROUND_DOWN(DirContext->DirIndex * sizeof(FAT_DIR_ENTRY), PAGE_SIZE);
{
if (dirMap == 0)
{
- DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
+ DPRINT (" long name entry found at %u\n", DirContext->DirIndex);
RtlZeroMemory(DirContext->LongNameU.Buffer, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
6, longNameEntry->name5_10,
2, longNameEntry->name11_12);
- index = (longNameEntry->id & 0x1f) - 1;
- dirMap |= 1 << index;
- pName = DirContext->LongNameU.Buffer + 13 * index;
-
- 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));
+ index = longNameEntry->id & 0x3f; // Note: it can be 0 for corrupted FS
+
+ /* Make sure index is valid and we have enaugh space in buffer
+ (we count one char for \0) */
+ if (index > 0 &&
+ index * 13 < DirContext->LongNameU.MaximumLength / sizeof(WCHAR))
+ {
+ index--; // make index 0 based
+ dirMap |= 1 << index;
+
+ pName = DirContext->LongNameU.Buffer + index * 13;
+ 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));
+
+ if (longNameEntry->id & 0x40)
+ {
+ /* It's last LFN entry. Terminate filename with \0 */
+ pName[13] = UNICODE_NULL;
+ }
+ }
+ else
+ DPRINT1("Long name entry has invalid index: %x!\n", longNameEntry->id);
DPRINT (" longName: [%S]\n", DirContext->LongNameU.Buffer);
}
}
+ /* Make sure filename is NULL terminate and calculate length */
+ DirContext->LongNameU.Buffer[DirContext->LongNameU.MaximumLength / sizeof(WCHAR) - 1]
+ = UNICODE_NULL;
DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR);
+
+ /* Init short name */
vfat8Dot3ToString(&DirContext->DirEntry.Fat, &DirContext->ShortNameU);
+ /* If we found no LFN, use short name as long */
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)
+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;
-
- 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);
- }
- FileOffset.u.LowPart = ROUND_DOWN(DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE);
- if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
- !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 = DirContext->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++;
- DirIndex++;
- if ((DirIndex % FATX_ENTRIES_PER_PAGE) == 0)
- {
- CcUnpinData(*pContext);
- FileOffset.u.LowPart += PAGE_SIZE;
- if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
- !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
- {
+ LARGE_INTEGER FileOffset;
+ PFATX_DIR_ENTRY fatxDirEntry;
+ OEM_STRING StringO;
+ ULONG DirIndex = DirContext->DirIndex;
+
+ FileOffset.u.HighPart = 0;
+
+ UNREFERENCED_PARAMETER(First);
+
+ if (!vfatFCBIsRoot(pDirFcb))
+ {
+ /* need to add . and .. entries */
+ switch (DirContext->DirIndex)
+ {
+ case 0: /* entry . */
+ DirContext->ShortNameU.Buffer[0] = 0;
+ DirContext->ShortNameU.Length = 0;
+ wcscpy(DirContext->LongNameU.Buffer, 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;
+ wcscpy(DirContext->LongNameU.Buffer, 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);
+ }
+ FileOffset.u.LowPart = ROUND_DOWN(DirIndex * sizeof(FATX_DIR_ENTRY), PAGE_SIZE);
+ if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
+ !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 = DirContext->DirIndex;
+
+ while (TRUE)
+ {
+ if (FATX_ENTRY_END(fatxDirEntry))
+ {
+ CcUnpinData(*pContext);
*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 = (PCHAR)fatxDirEntry->Filename;
- StringO.Length = StringO.MaximumLength = fatxDirEntry->FilenameLength;
- RtlOemStringToUnicodeString(&DirContext->LongNameU, &StringO, FALSE);
- return STATUS_SUCCESS;
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ if (!FATX_ENTRY_DELETED(fatxDirEntry))
+ {
+ RtlCopyMemory(&DirContext->DirEntry.FatX, fatxDirEntry, sizeof(FATX_DIR_ENTRY));
+ break;
+ }
+ DirContext->DirIndex++;
+ DirContext->StartIndex++;
+ DirIndex++;
+ if ((DirIndex % FATX_ENTRIES_PER_PAGE) == 0)
+ {
+ CcUnpinData(*pContext);
+ FileOffset.u.LowPart += PAGE_SIZE;
+ if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
+ !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
+ {
+ *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 = (PCHAR)fatxDirEntry->Filename;
+ StringO.Length = StringO.MaximumLength = fatxDirEntry->FilenameLength;
+ RtlOemStringToUnicodeString(&DirContext->LongNameU, &StringO, FALSE);
+ return STATUS_SUCCESS;
}