mirror of
https://github.com/winfsp/winfsp.git
synced 2025-06-08 04:52:10 -05:00
tst: passthrough: ReadDirectory improvements
This commit is contained in:
parent
2ced698256
commit
a5f8736b1e
@ -38,6 +38,8 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
|
PVOID DirBuffer;
|
||||||
|
ULONG DirBufferCapacity, DirBufferLength;
|
||||||
} PTFS_FILE_CONTEXT;
|
} PTFS_FILE_CONTEXT;
|
||||||
|
|
||||||
static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo)
|
static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo)
|
||||||
@ -165,6 +167,7 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileContext = malloc(sizeof *FileContext);
|
FileContext = malloc(sizeof *FileContext);
|
||||||
if (0 == FileContext)
|
if (0 == FileContext)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
memset(FileContext, 0, sizeof *FileContext);
|
||||||
|
|
||||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||||
@ -220,6 +223,7 @@ static NTSTATUS Open(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileContext = malloc(sizeof *FileContext);
|
FileContext = malloc(sizeof *FileContext);
|
||||||
if (0 == FileContext)
|
if (0 == FileContext)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
memset(FileContext, 0, sizeof *FileContext);
|
||||||
|
|
||||||
CreateFlags = FILE_FLAG_BACKUP_SEMANTICS;
|
CreateFlags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
if (CreateOptions & FILE_DELETE_ON_CLOSE)
|
if (CreateOptions & FILE_DELETE_ON_CLOSE)
|
||||||
@ -298,6 +302,7 @@ static VOID Close(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
free(((PTFS_FILE_CONTEXT *)FileContext)->DirBuffer);
|
||||||
free(FileContext);
|
free(FileContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,12 +507,32 @@ static NTSTATUS SetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOLEAN AddDirInfo(PTFS_FILE_CONTEXT *FileContext, FSP_FSCTL_DIR_INFO *DirInfo)
|
||||||
|
{
|
||||||
|
while (!FspFileSystemAddDirInfo(DirInfo,
|
||||||
|
FileContext->DirBuffer, FileContext->DirBufferCapacity, &FileContext->DirBufferLength))
|
||||||
|
{
|
||||||
|
PVOID Buffer;
|
||||||
|
ULONG Capacity = FileContext->DirBufferCapacity ? FileContext->DirBufferCapacity * 2 : 256;
|
||||||
|
|
||||||
|
Buffer = realloc(FileContext->DirBuffer, Capacity);
|
||||||
|
if (0 == Buffer)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
FileContext->DirBuffer = Buffer;
|
||||||
|
FileContext->DirBufferCapacity = Capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PVOID FileContext, PVOID Buffer, UINT64 Offset, ULONG BufferLength,
|
PVOID FileContext0, PVOID Buffer, UINT64 Offset, ULONG BufferLength,
|
||||||
PWSTR Pattern,
|
PWSTR Pattern,
|
||||||
PULONG PBytesTransferred)
|
PULONG PBytesTransferred)
|
||||||
{
|
{
|
||||||
PTFS *Ptfs = (PTFS *)FileSystem->UserContext;
|
PTFS *Ptfs = (PTFS *)FileSystem->UserContext;
|
||||||
|
PTFS_FILE_CONTEXT *FileContext = FileContext0;
|
||||||
HANDLE Handle = HandleFromContext(FileContext);
|
HANDLE Handle = HandleFromContext(FileContext);
|
||||||
WCHAR FullPath[FULLPATH_SIZE];
|
WCHAR FullPath[FULLPATH_SIZE];
|
||||||
ULONG Length, PatternLength;
|
ULONG Length, PatternLength;
|
||||||
@ -521,87 +546,70 @@ static NTSTATUS ReadDirectory(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D;
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D;
|
||||||
UINT64 NextOffset = 0;
|
UINT64 NextOffset = 0;
|
||||||
|
|
||||||
if (0 == Pattern)
|
if (0 == Offset)
|
||||||
Pattern = L"*";
|
|
||||||
PatternLength = (ULONG)wcslen(Pattern);
|
|
||||||
|
|
||||||
Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0);
|
|
||||||
if (0 == Length)
|
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
|
||||||
if (Length + 1 + PatternLength >= FULLPATH_SIZE)
|
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
|
||||||
|
|
||||||
if (L'\\' != FullPath[Length - 1])
|
|
||||||
FullPath[Length++] = L'\\';
|
|
||||||
memcpy(FullPath + Length, Pattern, PatternLength * sizeof(WCHAR));
|
|
||||||
FullPath[Length + PatternLength] = L'\0';
|
|
||||||
|
|
||||||
FindHandle = FindFirstFileW(FullPath, &FindData);
|
|
||||||
if (INVALID_HANDLE_VALUE == FindHandle)
|
|
||||||
{
|
{
|
||||||
/* add "End-Of-Listing" marker */
|
if (0 == Pattern)
|
||||||
FspFileSystemAddDirInfo(0, Buffer, BufferLength, PBytesTransferred);
|
Pattern = L"*";
|
||||||
return STATUS_SUCCESS;
|
PatternLength = (ULONG)wcslen(Pattern);
|
||||||
|
|
||||||
|
Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0);
|
||||||
|
if (0 == Length)
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
if (Length + 1 + PatternLength >= FULLPATH_SIZE)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
|
||||||
|
if (L'\\' != FullPath[Length - 1])
|
||||||
|
FullPath[Length++] = L'\\';
|
||||||
|
memcpy(FullPath + Length, Pattern, PatternLength * sizeof(WCHAR));
|
||||||
|
FullPath[Length + PatternLength] = L'\0';
|
||||||
|
|
||||||
|
FindHandle = FindFirstFileW(FullPath, &FindData);
|
||||||
|
if (INVALID_HANDLE_VALUE != FindHandle)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
memset(DirInfo, 0, sizeof *DirInfo);
|
||||||
|
Length = (ULONG)wcslen(FindData.cFileName);
|
||||||
|
DirInfo->Size = (UINT16)(FIELD_OFFSET(FSP_FSCTL_DIR_INFO, 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;
|
||||||
|
DirInfo->NextOffset = (NextOffset += FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size));
|
||||||
|
memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR));
|
||||||
|
|
||||||
|
if (!AddDirInfo(FileContext, DirInfo))
|
||||||
|
break;
|
||||||
|
} while (FindNextFileW(FindHandle, &FindData));
|
||||||
|
|
||||||
|
FindClose(FindHandle);
|
||||||
|
|
||||||
|
if (!AddDirInfo(FileContext, 0))
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
if (0 != FileContext->DirBuffer)
|
||||||
{
|
{
|
||||||
/*
|
for (DirInfo = (PVOID)((PUINT8)FileContext->DirBuffer + Offset);
|
||||||
* NOTE: The root directory does not have the dot (".", "..") entries
|
0 != DirInfo->Size;
|
||||||
* under Windows. This sample file system always adds them regardless.
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)))
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The simple conditional `Offset <= NextOffset++` only works when files
|
|
||||||
* are not created/deleted in the directory while it is being read.
|
|
||||||
* This is perhaps ok for this sample file system, but a "real" file
|
|
||||||
* system would probably have to handle this better.
|
|
||||||
*
|
|
||||||
* The best approach for a file system is to use directory offsets that
|
|
||||||
* do not change when files are created/deleted. If this is not possible
|
|
||||||
* it is also acceptable to have directory offsets that do not change
|
|
||||||
* for as long as the directory remains open.
|
|
||||||
*
|
|
||||||
* The easiest method to achieve this is to buffer all directory contents
|
|
||||||
* in a call to ReadDirectory with Offset == 0 and then return offsets
|
|
||||||
* within the directory content buffer. Subsequent ReadDirectory operations
|
|
||||||
* return directory contents directly from the buffer.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (Offset <= NextOffset++)
|
|
||||||
{
|
{
|
||||||
memset(DirInfo, 0, sizeof *DirInfo);
|
|
||||||
Length = (ULONG)wcslen(FindData.cFileName);
|
|
||||||
DirInfo->Size = (UINT16)(FIELD_OFFSET(FSP_FSCTL_DIR_INFO, 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;
|
|
||||||
DirInfo->NextOffset = NextOffset;
|
|
||||||
memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR));
|
|
||||||
|
|
||||||
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, BufferLength, PBytesTransferred))
|
if (!FspFileSystemAddDirInfo(DirInfo, Buffer, BufferLength, PBytesTransferred))
|
||||||
break;
|
return STATUS_SUCCESS;
|
||||||
}
|
|
||||||
|
|
||||||
if (!FindNextFileW(FindHandle, &FindData))
|
|
||||||
{
|
|
||||||
/* add "End-Of-Listing" marker */
|
|
||||||
FspFileSystemAddDirInfo(0, Buffer, BufferLength, PBytesTransferred);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FindClose(FindHandle);
|
/* add "End-Of-Listing" marker */
|
||||||
|
FspFileSystemAddDirInfo(0, Buffer, BufferLength, PBytesTransferred);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user