- Make this shit readable -- oh wait this is a commit message... Clean up indentation a bit.

svn path=/trunk/; revision=37779
This commit is contained in:
Stefan Ginsberg 2008-11-30 20:12:04 +00:00
parent f3818b0b92
commit eaac85ec75

View file

@ -17,137 +17,155 @@ ULONG
vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt, vfatDirEntryGetFirstCluster (PDEVICE_EXTENSION pDeviceExt,
PDIR_ENTRY pFatDirEntry) PDIR_ENTRY pFatDirEntry)
{ {
ULONG cluster; ULONG cluster;
if (pDeviceExt->FatInfo.FatType == FAT32) if (pDeviceExt->FatInfo.FatType == FAT32)
{ {
cluster = pFatDirEntry->Fat.FirstCluster | cluster = pFatDirEntry->Fat.FirstCluster |
(pFatDirEntry->Fat.FirstClusterHigh << 16); (pFatDirEntry->Fat.FirstClusterHigh << 16);
} }
else if (pDeviceExt->Flags & VCB_IS_FATX) else if (pDeviceExt->Flags & VCB_IS_FATX)
{ {
cluster = pFatDirEntry->FatX.FirstCluster; cluster = pFatDirEntry->FatX.FirstCluster;
} }
else else
{ {
cluster = pFatDirEntry->Fat.FirstCluster; cluster = pFatDirEntry->Fat.FirstCluster;
} }
return cluster; return cluster;
} }
static BOOLEAN FATIsDirectoryEmpty(PVFATFCB Fcb) static
BOOLEAN
FATIsDirectoryEmpty(PVFATFCB Fcb)
{ {
LARGE_INTEGER FileOffset; LARGE_INTEGER FileOffset;
PVOID Context = NULL; PVOID Context = NULL;
PFAT_DIR_ENTRY FatDirEntry; PFAT_DIR_ENTRY FatDirEntry;
ULONG Index, MaxIndex; ULONG Index, MaxIndex;
if (vfatFCBIsRoot(Fcb)) if (vfatFCBIsRoot(Fcb))
{ {
Index = 0; Index = 0;
} }
else else
{ {
Index = 2; Index = 2;
} }
FileOffset.QuadPart = 0; FileOffset.QuadPart = 0;
MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY); MaxIndex = Fcb->RFCB.FileSize.u.LowPart / sizeof(FAT_DIR_ENTRY);
while (Index < MaxIndex) while (Index < MaxIndex)
{ {
if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0) if (Context == NULL || (Index % FAT_ENTRIES_PER_PAGE) == 0)
{ {
if (Context != NULL) if (Context != NULL)
{ {
CcUnpinData(Context); CcUnpinData(Context);
} }
if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatDirEntry))
{
return TRUE;
}
FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
}
if (FAT_ENTRY_END(FatDirEntry))
{
CcUnpinData(Context);
return TRUE;
}
if (!FAT_ENTRY_DELETED(FatDirEntry))
{
CcUnpinData(Context);
return FALSE;
}
Index++;
FatDirEntry++;
}
if (Context)
{
CcUnpinData(Context);
}
return TRUE;
}
static BOOLEAN FATXIsDirectoryEmpty(PVFATFCB Fcb) if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatDirEntry))
{ {
LARGE_INTEGER FileOffset; return TRUE;
PVOID Context = NULL; }
PFATX_DIR_ENTRY FatXDirEntry;
ULONG Index, MaxIndex;
Index = 0; FatDirEntry += Index % FAT_ENTRIES_PER_PAGE;
}
FileOffset.QuadPart = 0; if (FAT_ENTRY_END(FatDirEntry))
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); CcUnpinData(Context);
}
if (!CcMapData(Fcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&FatXDirEntry))
{
return TRUE; return TRUE;
} }
FatXDirEntry += Index % FATX_ENTRIES_PER_PAGE;
} if (!FAT_ENTRY_DELETED(FatDirEntry))
if (FATX_ENTRY_END(FatXDirEntry)) {
{ CcUnpinData(Context);
CcUnpinData(Context); return FALSE;
return TRUE; }
}
if (!FATX_ENTRY_DELETED(FatXDirEntry)) Index++;
{ FatDirEntry++;
CcUnpinData(Context); }
return FALSE;
} if (Context)
Index++; {
FatXDirEntry++; CcUnpinData(Context);
} }
if (Context)
{ return TRUE;
CcUnpinData(Context);
}
return TRUE;
} }
BOOLEAN VfatIsDirectoryEmpty(PVFATFCB Fcb) static
BOOLEAN
FATXIsDirectoryEmpty(PVFATFCB Fcb)
{ {
if (Fcb->Flags & FCB_IS_FATX_ENTRY) LARGE_INTEGER FileOffset;
return FATXIsDirectoryEmpty(Fcb); PVOID Context = NULL;
else PFATX_DIR_ENTRY FatXDirEntry;
return FATIsDirectoryEmpty(Fcb); ULONG Index = 0, MaxIndex;
FileOffset.QuadPart = 0;
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;
} }
NTSTATUS FATGetNextDirEntry(PVOID * pContext, BOOLEAN
PVOID * pPage, VfatIsDirectoryEmpty(PVFATFCB Fcb)
IN PVFATFCB pDirFcb, {
PVFAT_DIRENTRY_CONTEXT DirContext, if (Fcb->Flags & FCB_IS_FATX_ENTRY)
BOOLEAN First) return FATXIsDirectoryEmpty(Fcb);
else
return FATIsDirectoryEmpty(Fcb);
}
NTSTATUS
FATGetNextDirEntry(PVOID *pContext,
PVOID *pPage,
IN PVFATFCB pDirFcb,
PVFAT_DIRENTRY_CONTEXT DirContext,
BOOLEAN First)
{ {
ULONG dirMap; ULONG dirMap;
PWCHAR pName; PWCHAR pName;
@ -168,182 +186,198 @@ NTSTATUS FATGetNextDirEntry(PVOID * pContext,
if (*pContext == NULL || (DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0) if (*pContext == NULL || (DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
{ {
if (*pContext != NULL) if (*pContext != NULL)
{ {
CcUnpinData(*pContext); CcUnpinData(*pContext);
} }
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;
}
}
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;
}
}
fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE; fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry; longNameEntry = (slot*) fatDirEntry;
dirMap = 0; dirMap = 0;
if (First) if (First)
{ {
/* This is the first call to vfatGetNextDirEntry. Possible the start index points /* This is the first call to vfatGetNextDirEntry. Possible the start index points
* into a long name or points to a short name with an assigned long name. * 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 */ * We must go back to the real start of the entry */
while (DirContext->DirIndex > 0 && while (DirContext->DirIndex > 0 &&
!FAT_ENTRY_END(fatDirEntry) && !FAT_ENTRY_END(fatDirEntry) &&
!FAT_ENTRY_DELETED(fatDirEntry) && !FAT_ENTRY_DELETED(fatDirEntry) &&
((!FAT_ENTRY_LONG(fatDirEntry) && !Back) || ((!FAT_ENTRY_LONG(fatDirEntry) && !Back) ||
(FAT_ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40)))) (FAT_ENTRY_LONG(fatDirEntry) && !(longNameEntry->id & 0x40))))
{ {
DirContext->DirIndex--; DirContext->DirIndex--;
Back = TRUE; Back = TRUE;
if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == FAT_ENTRIES_PER_PAGE - 1) if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == FAT_ENTRIES_PER_PAGE - 1)
{ {
CcUnpinData(*pContext); CcUnpinData(*pContext);
FileOffset.u.LowPart -= PAGE_SIZE; FileOffset.u.LowPart -= PAGE_SIZE;
if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage)) !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{ {
*pContext = NULL; *pContext = NULL;
return STATUS_NO_MORE_ENTRIES; return STATUS_NO_MORE_ENTRIES;
} }
fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE; fatDirEntry = (PFAT_DIR_ENTRY)(*pPage) + DirContext->DirIndex % FAT_ENTRIES_PER_PAGE;
longNameEntry = (slot*) fatDirEntry; longNameEntry = (slot*) fatDirEntry;
} }
else else
{ {
fatDirEntry--; fatDirEntry--;
longNameEntry--; longNameEntry--;
} }
} }
if (Back && !FAT_ENTRY_END(fatDirEntry) && if (Back && !FAT_ENTRY_END(fatDirEntry) &&
(FAT_ENTRY_DELETED(fatDirEntry) || !FAT_ENTRY_LONG(fatDirEntry))) (FAT_ENTRY_DELETED(fatDirEntry) || !FAT_ENTRY_LONG(fatDirEntry)))
{ {
DirContext->DirIndex++; DirContext->DirIndex++;
if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
{ if ((DirContext->DirIndex % FAT_ENTRIES_PER_PAGE) == 0)
CcUnpinData(*pContext); {
FileOffset.u.LowPart += PAGE_SIZE; CcUnpinData(*pContext);
if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart || FileOffset.u.LowPart += PAGE_SIZE;
!CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
{ if (FileOffset.u.LowPart >= pDirFcb->RFCB.FileSize.u.LowPart ||
*pContext = NULL; !CcMapData(pDirFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, pContext, pPage))
return STATUS_NO_MORE_ENTRIES; {
} *pContext = NULL;
fatDirEntry = (PFAT_DIR_ENTRY)*pPage; return STATUS_NO_MORE_ENTRIES;
longNameEntry = (slot*) *pPage; }
}
else fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
{ longNameEntry = (slot*) *pPage;
fatDirEntry++; }
longNameEntry++; else
} {
} fatDirEntry++;
} longNameEntry++;
}
}
}
DirContext->StartIndex = DirContext->DirIndex; DirContext->StartIndex = DirContext->DirIndex;
CheckSum = 0; CheckSum = 0;
while (TRUE) while (TRUE)
{ {
if (FAT_ENTRY_END(fatDirEntry)) if (FAT_ENTRY_END(fatDirEntry))
{ {
CcUnpinData(*pContext); CcUnpinData(*pContext);
*pContext = NULL; *pContext = NULL;
return STATUS_NO_MORE_ENTRIES; return STATUS_NO_MORE_ENTRIES;
} }
if (FAT_ENTRY_DELETED(fatDirEntry))
{
dirMap = 0;
DirContext->LongNameU.Buffer[0] = 0;
DirContext->StartIndex = DirContext->DirIndex + 1;
}
else
{
if (FAT_ENTRY_LONG(fatDirEntry))
{
if (dirMap == 0)
{
DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
RtlZeroMemory(DirContext->LongNameU.Buffer, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
}
if (FAT_ENTRY_DELETED(fatDirEntry)) DPRINT(" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n",
{ 5, longNameEntry->name0_4,
dirMap = 0; 6, longNameEntry->name5_10,
DirContext->LongNameU.Buffer[0] = 0; 2, longNameEntry->name11_12);
DirContext->StartIndex = DirContext->DirIndex + 1;
}
else
{
if (FAT_ENTRY_LONG(fatDirEntry))
{
if (dirMap == 0)
{
DPRINT (" long name entry found at %d\n", DirContext->DirIndex);
RtlZeroMemory(DirContext->LongNameU.Buffer, DirContext->LongNameU.MaximumLength);
CheckSum = longNameEntry->alias_checksum;
Valid = TRUE;
}
DPRINT (" name chunk1:[%.*S] chunk2:[%.*S] chunk3:[%.*S]\n", index = (longNameEntry->id & 0x1f) - 1;
5, longNameEntry->name0_4, dirMap |= 1 << index;
6, longNameEntry->name5_10, pName = DirContext->LongNameU.Buffer + 13 * index;
2, longNameEntry->name11_12);
index = (longNameEntry->id & 0x1f) - 1; RtlCopyMemory(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR));
dirMap |= 1 << index; RtlCopyMemory(pName + 5, longNameEntry->name5_10, 6 * sizeof(WCHAR));
pName = DirContext->LongNameU.Buffer + 13 * index; RtlCopyMemory(pName + 11, longNameEntry->name11_12, 2 * sizeof(WCHAR));
RtlCopyMemory(pName, longNameEntry->name0_4, 5 * sizeof(WCHAR)); DPRINT (" longName: [%S]\n", DirContext->LongNameU.Buffer);
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)
if (CheckSum != longNameEntry->alias_checksum) {
{ DPRINT1("Found wrong alias checksum in long name entry (first %x, current %x, %S)\n",
DPRINT1("Found wrong alias checksum in long name entry (first %x, current %x, %S)\n", CheckSum, longNameEntry->alias_checksum, DirContext->LongNameU.Buffer);
CheckSum, longNameEntry->alias_checksum, DirContext->LongNameU.Buffer); Valid = FALSE;
Valid = FALSE; }
} }
} else
else {
{ shortCheckSum = 0;
shortCheckSum = 0;
for (i = 0; i < 11; i++) for (i = 0; i < 11; i++)
{ {
shortCheckSum = (((shortCheckSum & 1) << 7) shortCheckSum = (((shortCheckSum & 1) << 7)
| ((shortCheckSum & 0xfe) >> 1)) | ((shortCheckSum & 0xfe) >> 1))
+ fatDirEntry->ShortName[i]; + fatDirEntry->ShortName[i];
} }
if (shortCheckSum != CheckSum && DirContext->LongNameU.Buffer[0])
{ if (shortCheckSum != CheckSum && DirContext->LongNameU.Buffer[0])
DPRINT1("Checksum from long and short name is not equal (short: %x, long: %x, %S)\n", {
shortCheckSum, CheckSum, DirContext->LongNameU.Buffer); DPRINT1("Checksum from long and short name is not equal (short: %x, long: %x, %S)\n",
DirContext->LongNameU.Buffer[0] = 0; shortCheckSum, CheckSum, DirContext->LongNameU.Buffer);
} DirContext->LongNameU.Buffer[0] = 0;
if (Valid == FALSE) }
{
DirContext->LongNameU.Buffer[0] = 0; if (Valid == FALSE)
} {
DirContext->LongNameU.Buffer[0] = 0;
}
RtlCopyMemory (&DirContext->DirEntry.Fat, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
DirContext->DirIndex++;
if ((DirContext->DirIndex % FAT_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;
}
fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
longNameEntry = (slot*) *pPage;
}
else
{
fatDirEntry++;
longNameEntry++;
}
}
RtlCopyMemory (&DirContext->DirEntry.Fat, fatDirEntry, sizeof (FAT_DIR_ENTRY));
break;
}
}
DirContext->DirIndex++;
if ((DirContext->DirIndex % FAT_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;
}
fatDirEntry = (PFAT_DIR_ENTRY)*pPage;
longNameEntry = (slot*) *pPage;
}
else
{
fatDirEntry++;
longNameEntry++;
}
}
DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR); DirContext->LongNameU.Length = wcslen(DirContext->LongNameU.Buffer) * sizeof(WCHAR);
vfat8Dot3ToString(&DirContext->DirEntry.Fat, &DirContext->ShortNameU); vfat8Dot3ToString(&DirContext->DirEntry.Fat, &DirContext->ShortNameU);
if (DirContext->LongNameU.Length == 0) if (DirContext->LongNameU.Length == 0)
{ {
RtlCopyUnicodeString(&DirContext->LongNameU, &DirContext->ShortNameU); RtlCopyUnicodeString(&DirContext->LongNameU, &DirContext->ShortNameU);
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }