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; return _FileSystem;
} }
/* helpers: directories/streams */ /* helpers */
static BOOLEAN AcquireDirectoryBuffer(PVOID *PDirBuffer, NTSTATUS SeekableReadDirectory(
BOOLEAN Reset, PNTSTATUS PResult) PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID Buffer,
ULONG Length,
PULONG PBytesTransferred)
{ {
return FspFileSystemAcquireDirectoryBuffer(PDirBuffer, Reset, PResult); PVOID Context = 0;
} union
static BOOLEAN FillDirectoryBuffer(PVOID *PDirBuffer,
DirInfo *DirInfo, PNTSTATUS PResult)
{ {
return FspFileSystemFillDirectoryBuffer(PDirBuffer, DirInfo, PResult); 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;
} }
static VOID ReleaseDirectoryBuffer(PVOID *PDirBuffer) 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); FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
throw;
} }
static VOID ReadDirectoryBuffer(PVOID *PDirBuffer, FspFileSystemReleaseDirectoryBuffer(PDirBuffer);
PWSTR Marker, }
PVOID Buffer, ULONG Length, PULONG PBytesTransferred) if (!NT_SUCCESS(Result))
{ return Result;
FspFileSystemReadDirectoryBuffer(PDirBuffer, FspFileSystemReadDirectoryBuffer(PDirBuffer, Marker, Buffer, Length, PBytesTransferred);
Marker, Buffer, Length, PBytesTransferred); return STATUS_SUCCESS;
} }
static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer) static VOID DeleteDirectoryBuffer(PVOID *PDirBuffer)
{ {
FspFileSystemDeleteDirectoryBuffer(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( BOOLEAN FindReparsePoint(
PWSTR FileName, PUINT32 PReparsePointIndex) PWSTR FileName, PUINT32 PReparsePointIndex)
{ {
@ -288,6 +339,11 @@ public:
CurrentReparseData, CurrentReparseDataSize, CurrentReparseData, CurrentReparseDataSize,
ReplaceReparseData, ReplaceReparseDataSize); ReplaceReparseData, ReplaceReparseDataSize);
} }
static BOOLEAN AddStreamInfo(StreamInfo *StreamInfo,
PVOID Buffer, ULONG Length, PULONG PBytesTransferred)
{
return FspFileSystemAddStreamInfo(StreamInfo, Buffer, Length, PBytesTransferred);
}
protected: protected:
/* operations */ /* operations */
@ -460,6 +516,16 @@ protected:
{ {
return STATUS_INVALID_DEVICE_REQUEST; 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( virtual NTSTATUS ResolveReparsePoints(
PWSTR FileName, PWSTR FileName,
UINT32 ReparsePointIndex, UINT32 ReparsePointIndex,

View File

@ -148,6 +148,13 @@ protected:
PVOID Buffer, PVOID Buffer,
ULONG Length, ULONG Length,
PULONG PBytesTransferred); PULONG PBytesTransferred);
NTSTATUS ReadDirectoryEntry(
PVOID FileNode,
PVOID FileDesc,
PWSTR Pattern,
PWSTR Marker,
PVOID *PContext,
DirInfo *DirInfo);
private: private:
PWSTR _Path; PWSTR _Path;
@ -729,8 +736,21 @@ NTSTATUS Ptfs::ReadDirectory(
PWSTR Pattern, PWSTR Pattern,
PWSTR Marker, PWSTR Marker,
PVOID Buffer, PVOID Buffer,
ULONG BufferLength, ULONG Length,
PULONG PBytesTransferred) 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; PtfsFileDesc *FileDesc = (PtfsFileDesc *)FileDesc0;
HANDLE Handle = FileDesc->Handle; HANDLE Handle = FileDesc->Handle;
@ -738,16 +758,8 @@ NTSTATUS Ptfs::ReadDirectory(
ULONG Length, PatternLength; ULONG Length, PatternLength;
HANDLE FindHandle; HANDLE FindHandle;
WIN32_FIND_DATAW FindData; 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 (0 == *PContext)
if (AcquireDirectoryBuffer(&FileDesc->DirBuffer, 0 == Marker, &DirBufferResult))
{ {
if (0 == Pattern) if (0 == Pattern)
Pattern = L"*"; Pattern = L"*";
@ -755,14 +767,9 @@ NTSTATUS Ptfs::ReadDirectory(
Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0); Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0);
if (0 == Length) if (0 == Length)
DirBufferResult = NtStatusFromWin32(GetLastError()); return NtStatusFromWin32(GetLastError());
else if (Length + 1 + PatternLength >= FULLPATH_SIZE) if (Length + 1 + PatternLength >= FULLPATH_SIZE)
DirBufferResult = STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
if (!NT_SUCCESS(DirBufferResult))
{
ReleaseDirectoryBuffer(&FileDesc->DirBuffer);
return DirBufferResult;
}
if (L'\\' != FullPath[Length - 1]) if (L'\\' != FullPath[Length - 1])
FullPath[Length++] = L'\\'; FullPath[Length++] = L'\\';
@ -770,14 +777,24 @@ NTSTATUS Ptfs::ReadDirectory(
FullPath[Length + PatternLength] = L'\0'; FullPath[Length + PatternLength] = L'\0';
FindHandle = FindFirstFileW(FullPath, &FindData); FindHandle = FindFirstFileW(FullPath, &FindData);
if (INVALID_HANDLE_VALUE != FindHandle) if (INVALID_HANDLE_VALUE == FindHandle)
return STATUS_NO_MORE_FILES;
*PContext = FindHandle;
}
else
{ {
do FindHandle = *PContext;
if (!FindNextFileW(FindHandle, &FindData))
{ {
FindClose(FindHandle);
return STATUS_NO_MORE_FILES;
}
}
memset(DirInfo, 0, sizeof *DirInfo); memset(DirInfo, 0, sizeof *DirInfo);
Length = (ULONG)wcslen(FindData.cFileName); Length = (ULONG)wcslen(FindData.cFileName);
DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + DirInfo->Size = (UINT16)(FIELD_OFFSET(FileSystem::DirInfo, FileNameBuf) + Length * sizeof(WCHAR));
Length * sizeof(WCHAR));
DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes; DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes;
DirInfo->FileInfo.ReparseTag = 0; DirInfo->FileInfo.ReparseTag = 0;
DirInfo->FileInfo.FileSize = DirInfo->FileInfo.FileSize =
@ -792,22 +809,6 @@ NTSTATUS Ptfs::ReadDirectory(
DirInfo->FileInfo.HardLinks = 0; DirInfo->FileInfo.HardLinks = 0;
memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR)); memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR));
if (!FillDirectoryBuffer(&FileDesc->DirBuffer, DirInfo, &DirBufferResult))
break;
} while (FindNextFileW(FindHandle, &FindData));
FindClose(FindHandle);
}
ReleaseDirectoryBuffer(&FileDesc->DirBuffer);
}
if (!NT_SUCCESS(DirBufferResult))
return DirBufferResult;
ReadDirectoryBuffer(&FileDesc->DirBuffer,
Marker, Buffer, BufferLength, PBytesTransferred);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }