inc: winfsp.hpp: FileSystem: ReadDirectoryEntry and friends

This commit is contained in:
Bill Zissimopoulos 2017-04-14 00:01:08 -07:00
parent 4c102ab57c
commit 8787f2c528
2 changed files with 148 additions and 81 deletions

View File

@ -236,44 +236,95 @@ public:
return _FileSystem;
}
/* helpers: directories/streams */
static BOOLEAN AcquireDirectoryBuffer(PVOID *PDirBuffer,
BOOLEAN Reset, PNTSTATUS PResult)
{
return FspFileSystemAcquireDirectoryBuffer(PDirBuffer, Reset, PResult);
}
static BOOLEAN FillDirectoryBuffer(PVOID *PDirBuffer,
DirInfo *DirInfo, PNTSTATUS PResult)
{
return FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, PResult);
}
static VOID ReleaseDirectoryBuffer(PVOID *PDirBuffer)
{
FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
}
static VOID ReadDirectoryBuffer(PVOID *PDirBuffer,
/* helpers */
NTSTATUS SeekableReadDirectory(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
FspFileSystemReadDirectoryBuffer(PDirBuffer,
Marker, Buffer, Length, PBytesTransferred);
PVOID Context = 0;
union
{
UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
FileSystem::DirInfo D;
} DirInfoBuf;
FileSystem::DirInfo *DirInfo = &DirInfoBuf.D;
NTSTATUS Result = STATUS_SUCCESS;
*PBytesTransferred = 0;
for (;;)
{
Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo);
if (STATUS_NO_MORE_FILES == Result)
{
Result = STATUS_SUCCESS;
break;
}
if (!NT_SUCCESS(Result))
break;
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred))
break;
}
if (!NT_SUCCESS(Result))
return Result;
return STATUS_SUCCESS;
}
NTSTATUS BufferedReadDirectory(
PVOID *PDirBuffer,
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{
PVOID Context = 0;
union
{
UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
FileSystem::DirInfo D;
} DirInfoBuf;
FileSystem::DirInfo *DirInfo = &DirInfoBuf.D;
NTSTATUS Result = STATUS_SUCCESS;
*PBytesTransferred = 0;
if (FspFileSystemAcquireDirectoryBuffer(PDirBuffer, 0 == Marker, &Result))
{
try
{
for (;;)
{
Result = ReadDirectoryEntry(FileNode, FileDesc, Pattern, Marker, &Context, DirInfo);
if (STATUS_NO_MORE_FILES == Result)
{
Result = STATUS_SUCCESS;
break;
}
if (!NT_SUCCESS(Result))
break;
if (!FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, &Result))
break;
}
}
catch (...)
{
FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
throw;
}
FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
}
if (!NT_SUCCESS(Result))
return Result;
FspFileSystemReadDirectoryBuffer(PDirBuffer, Marker, Buffer, Length, PBytesTransferred);
return STATUS_SUCCESS;
}
static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer)
{
FspFileSystemDeleteDirectoryBuffer(PDirBuffer);
}
static BOOLEAN AddDirInfo(DirInfo *DirInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
return FspFileSystemAddDirInfo(DirInfo, Buffer, Length, PBytesTransferred);
}
static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred);
}
/* helpers: reparse points */
BOOLEAN FindReparsePoint(
PWSTR FileName, PUINT32 PReparsePointIndex)
{
@ -288,6 +339,11 @@ public:
CurrentReparseData, CurrentReparseDataSize,
ReplaceReparseData, ReplaceReparseDataSize);
}
static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred);
}
protected:
/* operations */
@ -460,6 +516,16 @@ protected:
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS ReadDirectoryEntry(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID *PContext,
DirInfo *DirInfo)
{
return STATUS_INVALID_DEVICE_REQUEST;
}
virtual NTSTATUS ResolveReparsePoints(
PWSTR FileName,
UINT32 ReparsePointIndex,

View File

@ -148,6 +148,13 @@ protected:
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred);
NTSTATUS ReadDirectoryEntry(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID *PContext,
DirInfo *DirInfo);
private:
PWSTR _Path;
@ -729,8 +736,21 @@ NTSTATUS Ptfs::ReadDirectory(
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG BufferLength,
ULONG Length,
PULONG PBytesTransferred)
{
PtfsFileDesc *FileDesc = (PtfsFileDesc *)FileDesc0;
return BufferedReadDirectory(&FileDesc->DirBuffer,
FileNode, FileDesc, Pattern, Marker, Buffer, Length, PBytesTransferred);
}
NTSTATUS Ptfs::ReadDirectoryEntry(
PVOID FileNode,
PVOID FileDesc0,
PWSTR Pattern,
PWSTR Marker,
PVOID *PContext,
DirInfo *DirInfo)
{
PtfsFileDesc *FileDesc = (PtfsFileDesc *)FileDesc0;
HANDLE Handle = FileDesc->Handle;
@ -738,16 +758,8 @@ NTSTATUS Ptfs::ReadDirectory(
ULONG Length, PatternLength;
HANDLE FindHandle;
WIN32_FIND_DATAW FindData;
union
{
UINT8 B[FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + MAX_PATH * sizeof(WCHAR)];
FileSystem::DirInfo D;
} DirInfoBuf;
FileSystem::DirInfo *DirInfo = &DirInfoBuf.D;
NTSTATUS DirBufferResult;
DirBufferResult = STATUS_SUCCESS;
if (AcquireDirectoryBuffer(&FileDesc->DirBuffer, 0 == Marker, &DirBufferResult))
if (0 == *PContext)
{
if (0 == Pattern)
Pattern = L"*";
@ -755,14 +767,9 @@ NTSTATUS Ptfs::ReadDirectory(
Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0);
if (0 == Length)
DirBufferResult = NtStatusFromWin32(GetLastError());
else if (Length + 1 + PatternLength >= FULLPATH_SIZE)
DirBufferResult = STATUS_OBJECT_NAME_INVALID;
if (!NT_SUCCESS(DirBufferResult))
{
ReleaseDirectoryBuffer(&FileDesc->DirBuffer);
return DirBufferResult;
}
return NtStatusFromWin32(GetLastError());
if (Length + 1 + PatternLength >= FULLPATH_SIZE)
return STATUS_OBJECT_NAME_INVALID;
if (L'\\' != FullPath[Length - 1])
FullPath[Length++] = L'\\';
@ -770,43 +777,37 @@ NTSTATUS Ptfs::ReadDirectory(
FullPath[Length + PatternLength] = L'\0';
FindHandle = FindFirstFileW(FullPath, &FindData);
if (INVALID_HANDLE_VALUE != FindHandle)
if (INVALID_HANDLE_VALUE == FindHandle)
return STATUS_NO_MORE_FILES;
*PContext = FindHandle;
}
else
{
FindHandle = *PContext;
if (!FindNextFileW(FindHandle, &FindData))
{
do
{
memset(DirInfo, 0, sizeof *DirInfo);
Length = (ULONG)wcslen(FindData.cFileName);
DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) +
Length * sizeof(WCHAR));
DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes;
DirInfo->FileInfo.ReparseTag = 0;
DirInfo->FileInfo.FileSize =
((UINT64)FindData.nFileSizeHigh << 32) | (UINT64)FindData.nFileSizeLow;
DirInfo->FileInfo.AllocationSize = (DirInfo->FileInfo.FileSize + ALLOCATION_UNIT - 1)
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
DirInfo->FileInfo.CreationTime = ((PLARGE_INTEGER)&FindData.ftCreationTime)->QuadPart;
DirInfo->FileInfo.LastAccessTime = ((PLARGE_INTEGER)&FindData.ftLastAccessTime)->QuadPart;
DirInfo->FileInfo.LastWriteTime = ((PLARGE_INTEGER)&FindData.ftLastWriteTime)->QuadPart;
DirInfo->FileInfo.ChangeTime = DirInfo->FileInfo.LastWriteTime;
DirInfo->FileInfo.IndexNumber = 0;
DirInfo->FileInfo.HardLinks = 0;
memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR));
if (!FillDirectoryBuffer(&FileDesc->DirBuffer, DirInfo, &DirBufferResult))
break;
} while (FindNextFileW(FindHandle, &FindData));
FindClose(FindHandle);
return STATUS_NO_MORE_FILES;
}
ReleaseDirectoryBuffer(&FileDesc->DirBuffer);
}
if (!NT_SUCCESS(DirBufferResult))
return DirBufferResult;
ReadDirectoryBuffer(&FileDesc->DirBuffer,
Marker, Buffer, BufferLength, PBytesTransferred);
memset(DirInfo, 0, sizeof *DirInfo);
Length = (ULONG)wcslen(FindData.cFileName);
DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + Length * sizeof(WCHAR));
DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes;
DirInfo->FileInfo.ReparseTag = 0;
DirInfo->FileInfo.FileSize =
((UINT64)FindData.nFileSizeHigh << 32) | (UINT64)FindData.nFileSizeLow;
DirInfo->FileInfo.AllocationSize = (DirInfo->FileInfo.FileSize + ALLOCATION_UNIT - 1)
/ ALLOCATION_UNIT * ALLOCATION_UNIT;
DirInfo->FileInfo.CreationTime = ((PLARGE_INTEGER)&FindData.ftCreationTime)->QuadPart;
DirInfo->FileInfo.LastAccessTime = ((PLARGE_INTEGER)&FindData.ftLastAccessTime)->QuadPart;
DirInfo->FileInfo.LastWriteTime = ((PLARGE_INTEGER)&FindData.ftLastWriteTime)->QuadPart;
DirInfo->FileInfo.ChangeTime = DirInfo->FileInfo.LastWriteTime;
DirInfo->FileInfo.IndexNumber = 0;
DirInfo->FileInfo.HardLinks = 0;
memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR));
return STATUS_SUCCESS;
}