mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 13:26:17 +00:00
[NFI] Rewrite the way files are handled, this allows querying handling a new file while already handling one.
This is useful to fix the problem when a directory wasn't in cache yet, but one of its files is to be displayed.
This commit is contained in:
parent
2abb99faa9
commit
d849794a35
1 changed files with 121 additions and 65 deletions
|
@ -164,15 +164,37 @@ void PrintUsage(void)
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddToCache(PWSTR Name, DWORD Length, ULONGLONG MftId)
|
PNAME_CACHE_ENTRY FindInCache(ULONGLONG MftId)
|
||||||
{
|
{
|
||||||
PNAME_CACHE_ENTRY CacheEntry;
|
PNAME_CACHE_ENTRY CacheEntry;
|
||||||
|
|
||||||
|
for (CacheEntry = CacheHead; CacheEntry != NULL; CacheEntry = CacheEntry->Next)
|
||||||
|
{
|
||||||
|
if (MftId == CacheEntry->MftId)
|
||||||
|
{
|
||||||
|
return CacheEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PNAME_CACHE_ENTRY AddToCache(PWSTR Name, DWORD Length, ULONGLONG MftId)
|
||||||
|
{
|
||||||
|
PNAME_CACHE_ENTRY CacheEntry;
|
||||||
|
|
||||||
|
/* Don't add in cache if already there! */
|
||||||
|
CacheEntry = FindInCache(MftId);
|
||||||
|
if (CacheEntry != NULL)
|
||||||
|
{
|
||||||
|
return CacheEntry;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate an entry big enough to store name and cache info */
|
/* Allocate an entry big enough to store name and cache info */
|
||||||
CacheEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(NAME_CACHE_ENTRY) + Length);
|
CacheEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(NAME_CACHE_ENTRY) + Length);
|
||||||
if (CacheEntry == NULL)
|
if (CacheEntry == NULL)
|
||||||
{
|
{
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert in head (likely more perf) */
|
/* Insert in head (likely more perf) */
|
||||||
|
@ -182,28 +204,34 @@ void AddToCache(PWSTR Name, DWORD Length, ULONGLONG MftId)
|
||||||
CacheEntry->MftId = MftId;
|
CacheEntry->MftId = MftId;
|
||||||
CacheEntry->NameLen = Length;
|
CacheEntry->NameLen = Length;
|
||||||
CopyMemory(CacheEntry->Name, Name, Length);
|
CopyMemory(CacheEntry->Name, Name, Length);
|
||||||
|
|
||||||
|
return CacheEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintPrettyName(PNTFS_ATTR_RECORD Attributes, PNTFS_ATTR_RECORD AttributesEnd, ULONGLONG MftId)
|
PNAME_CACHE_ENTRY HandleFile(HANDLE VolumeHandle, PNTFS_VOLUME_DATA_BUFFER VolumeInfo, ULONGLONG Id, PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer, BOOLEAN Silent);
|
||||||
|
|
||||||
|
PNAME_CACHE_ENTRY PrintPrettyName(HANDLE VolumeHandle, PNTFS_VOLUME_DATA_BUFFER VolumeInfo, PNTFS_ATTR_RECORD Attributes, PNTFS_ATTR_RECORD AttributesEnd, ULONGLONG MftId, BOOLEAN Silent)
|
||||||
{
|
{
|
||||||
BOOLEAN FirstRun, Found;
|
BOOLEAN FirstRun;
|
||||||
PNTFS_ATTR_RECORD Attribute;
|
PNTFS_ATTR_RECORD Attribute;
|
||||||
|
|
||||||
FirstRun = TRUE;
|
FirstRun = TRUE;
|
||||||
Found = FALSE;
|
|
||||||
|
|
||||||
/* Setup name for "standard" files */
|
/* Setup name for "standard" files */
|
||||||
if (MftId <= NTFS_FILE_EXTEND)
|
if (MftId <= NTFS_FILE_EXTEND)
|
||||||
{
|
{
|
||||||
_tprintf(_T("%s\n"), KnownEntries[MftId]);
|
if (!Silent)
|
||||||
|
{
|
||||||
|
_tprintf(_T("%s\n"), KnownEntries[MftId]);
|
||||||
|
}
|
||||||
|
|
||||||
/* $Extend can contain entries, add it in cache */
|
/* $Extend can contain entries, add it in cache */
|
||||||
if (MftId == NTFS_FILE_EXTEND)
|
if (MftId == NTFS_FILE_EXTEND)
|
||||||
{
|
{
|
||||||
AddToCache(L"\\$Extend", sizeof(L"\\$Extend") - sizeof(UNICODE_NULL), NTFS_FILE_EXTEND);
|
return AddToCache(L"\\$Extend", sizeof(L"\\$Extend") - sizeof(UNICODE_NULL), NTFS_FILE_EXTEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We'll first try to use the Win32 name
|
/* We'll first try to use the Win32 name
|
||||||
|
@ -218,6 +246,7 @@ TryAgain:
|
||||||
PFILENAME_ATTRIBUTE Name;
|
PFILENAME_ATTRIBUTE Name;
|
||||||
ULONGLONG ParentId;
|
ULONGLONG ParentId;
|
||||||
ULONG Length;
|
ULONG Length;
|
||||||
|
PNAME_CACHE_ENTRY CacheEntry;
|
||||||
|
|
||||||
/* Move to the next arg if:
|
/* Move to the next arg if:
|
||||||
* - Not a file name
|
* - Not a file name
|
||||||
|
@ -251,19 +280,25 @@ TryAgain:
|
||||||
/* Default case */
|
/* Default case */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PNAME_CACHE_ENTRY CacheEntry;
|
|
||||||
|
|
||||||
/* Did we already cache the name? */
|
/* Did we already cache the name? */
|
||||||
for (CacheEntry = CacheHead; CacheEntry != NULL; CacheEntry = CacheEntry->Next)
|
CacheEntry = FindInCache(ParentId);
|
||||||
|
|
||||||
|
/* It wasn't in cache? Try to get it in! */
|
||||||
|
if (CacheEntry == NULL)
|
||||||
{
|
{
|
||||||
if (ParentId == CacheEntry->MftId)
|
PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer;
|
||||||
|
|
||||||
|
OutputBuffer = HeapAlloc(GetProcessHeap(), 0, VolumeInfo->BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER));
|
||||||
|
if (OutputBuffer != NULL)
|
||||||
{
|
{
|
||||||
break;
|
CacheEntry = HandleFile(VolumeHandle, VolumeInfo, ParentId, OutputBuffer, TRUE);
|
||||||
|
HeapFree(GetProcessHeap(), 0, OutputBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Nothing written yet */
|
/* Nothing written yet */
|
||||||
Length = 0;
|
Length = 0;
|
||||||
|
|
||||||
/* We cached it */
|
/* We cached it */
|
||||||
if (CacheEntry != NULL)
|
if (CacheEntry != NULL)
|
||||||
{
|
{
|
||||||
|
@ -275,7 +310,6 @@ TryAgain:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* FIXME: Do something, like trying to read parent... */
|
|
||||||
_tprintf(_T("Parent: %I64d\n"), ParentId);
|
_tprintf(_T("Parent: %I64d\n"), ParentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,20 +319,25 @@ TryAgain:
|
||||||
Display[Length] = UNICODE_NULL;
|
Display[Length] = UNICODE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display the name */
|
if (!Silent)
|
||||||
_tprintf(_T("%s\n"), Display);
|
{
|
||||||
|
/* Display the name */
|
||||||
|
_tprintf(_T("%s\n"), Display);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset cache entry */
|
||||||
|
CacheEntry = NULL;
|
||||||
|
|
||||||
/* If that's a directory, put it in the cache */
|
/* If that's a directory, put it in the cache */
|
||||||
if (Name->FileAttributes & NTFS_FILE_TYPE_DIRECTORY)
|
if (Name->FileAttributes & NTFS_FILE_TYPE_DIRECTORY)
|
||||||
{
|
{
|
||||||
AddToCache(Display, Length * sizeof(WCHAR), MftId);
|
CacheEntry = AddToCache(Display, Length * sizeof(WCHAR), MftId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, just quit */
|
/* Now, just quit */
|
||||||
FirstRun = FALSE;
|
FirstRun = FALSE;
|
||||||
Found = TRUE;
|
|
||||||
|
|
||||||
break;
|
return CacheEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If was first run (Win32 search), retry with other names */
|
/* If was first run (Win32 search), retry with other names */
|
||||||
|
@ -309,10 +348,12 @@ TryAgain:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we couldn't find a name, print unknown */
|
/* If we couldn't find a name, print unknown */
|
||||||
if (!Found)
|
if (!Silent)
|
||||||
{
|
{
|
||||||
_tprintf(_T("(unknown/unnamed)\n"));
|
_tprintf(_T("(unknown/unnamed)\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
|
PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
|
||||||
|
@ -463,6 +504,65 @@ void PrintAttributeInfo(PNTFS_ATTR_RECORD Attribute, DWORD MaxSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNAME_CACHE_ENTRY HandleFile(HANDLE VolumeHandle, PNTFS_VOLUME_DATA_BUFFER VolumeInfo, ULONGLONG Id, PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer, BOOLEAN Silent)
|
||||||
|
{
|
||||||
|
NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer;
|
||||||
|
PFILE_RECORD_HEADER FileRecord;
|
||||||
|
PNTFS_ATTR_RECORD Attribute, AttributesEnd;
|
||||||
|
DWORD LengthReturned;
|
||||||
|
PNAME_CACHE_ENTRY CacheEntry;
|
||||||
|
|
||||||
|
/* Get the file record */
|
||||||
|
InputBuffer.FileReferenceNumber.QuadPart = Id;
|
||||||
|
if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer, sizeof(InputBuffer),
|
||||||
|
OutputBuffer, VolumeInfo->BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER),
|
||||||
|
&LengthReturned, NULL))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't deal with it if we already browsed it
|
||||||
|
* FSCTL_GET_NTFS_FILE_RECORD always returns previous record if demanded
|
||||||
|
* isn't allocated
|
||||||
|
*/
|
||||||
|
if (OutputBuffer->FileReferenceNumber.QuadPart != Id)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer;
|
||||||
|
if (FileRecord->Ntfs.Type != NRH_FILE_TYPE)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Silent)
|
||||||
|
{
|
||||||
|
/* Print ID */
|
||||||
|
_tprintf(_T("\nFile %I64d\n"), OutputBuffer->FileReferenceNumber.QuadPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get attributes list */
|
||||||
|
Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
|
||||||
|
AttributesEnd = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
|
||||||
|
|
||||||
|
/* Print the file name */
|
||||||
|
CacheEntry = PrintPrettyName(VolumeHandle, VolumeInfo, Attribute, AttributesEnd, Id, Silent);
|
||||||
|
|
||||||
|
if (!Silent)
|
||||||
|
{
|
||||||
|
/* And print attributes information for each attribute */
|
||||||
|
while (Attribute < AttributesEnd && Attribute->Type != AttributeEnd)
|
||||||
|
{
|
||||||
|
PrintAttributeInfo(Attribute, VolumeInfo->BytesPerFileRecordSegment);
|
||||||
|
Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CacheEntry;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
__cdecl
|
__cdecl
|
||||||
_tmain(int argc, const TCHAR *argv[])
|
_tmain(int argc, const TCHAR *argv[])
|
||||||
|
@ -526,51 +626,7 @@ _tmain(int argc, const TCHAR *argv[])
|
||||||
/* Forever loop, extract all the files! */
|
/* Forever loop, extract all the files! */
|
||||||
for (File = 0;; ++File)
|
for (File = 0;; ++File)
|
||||||
{
|
{
|
||||||
NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer;
|
HandleFile(VolumeHandle, &VolumeInfo, File, OutputBuffer, FALSE);
|
||||||
PFILE_RECORD_HEADER FileRecord;
|
|
||||||
PNTFS_ATTR_RECORD Attribute, AttributesEnd;
|
|
||||||
|
|
||||||
/* Get the file record */
|
|
||||||
InputBuffer.FileReferenceNumber.QuadPart = File;
|
|
||||||
if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer, sizeof(InputBuffer),
|
|
||||||
OutputBuffer, VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER),
|
|
||||||
&LengthReturned, NULL))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't deal with it if we already browsed it
|
|
||||||
* FSCTL_GET_NTFS_FILE_RECORD always returns previous record if demanded
|
|
||||||
* isn't allocated
|
|
||||||
*/
|
|
||||||
if (OutputBuffer->FileReferenceNumber.QuadPart != File)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer;
|
|
||||||
if (FileRecord->Ntfs.Type != NRH_FILE_TYPE)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print ID */
|
|
||||||
_tprintf(_T("\nFile %I64d\n"), OutputBuffer->FileReferenceNumber.QuadPart);
|
|
||||||
|
|
||||||
/* Get attributes list */
|
|
||||||
Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
|
|
||||||
AttributesEnd = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
|
|
||||||
|
|
||||||
/* Print the file name */
|
|
||||||
PrintPrettyName(Attribute, AttributesEnd, File);
|
|
||||||
|
|
||||||
/* And print attributes information for each attribute */
|
|
||||||
while (Attribute < AttributesEnd && Attribute->Type != AttributeEnd)
|
|
||||||
{
|
|
||||||
PrintAttributeInfo(Attribute, VolumeInfo.BytesPerFileRecordSegment);
|
|
||||||
Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free memory! */
|
/* Free memory! */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue