mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 09:22:57 -05:00
Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
551ed341a7 | |||
52ffb47fee | |||
c208e0ecbd | |||
87389f010b | |||
c32b1c19c2 | |||
8ce6836674 |
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<MyCanonicalVersion>1.10</MyCanonicalVersion>
|
<MyCanonicalVersion>1.10</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2022 Beta4</MyProductVersion>
|
<MyProductVersion>2022 Beta5</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>Beta</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
@ -39,7 +39,7 @@
|
|||||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ResourceCompile>
|
<ResourceCompile>
|
||||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion)MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName)$(TargetExt).lib</ImportLibrary>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -124,6 +125,7 @@
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName)$(TargetExt).lib</ImportLibrary>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -137,6 +139,7 @@
|
|||||||
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
<ProgramDatabaseFile>$(OutDir)$(TargetFileName).pdb</ProgramDatabaseFile>
|
||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName)$(TargetExt).lib</ImportLibrary>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -151,6 +154,7 @@
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||||
|
<ImportLibrary>$(OutDir)$(TargetName)$(TargetExt).lib</ImportLibrary>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -114,7 +114,7 @@ static BOOLEAN FspFileSystemSearchDirectoryBuffer(FSP_FILE_SYSTEM_DIRECTORY_BUFF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*PIndexNum = Lo;
|
*PIndexNum = Hi;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
PVOID DirInfoBuffer;
|
PVOID DirInfoBuffer;
|
||||||
ULONG DirInfoSize;
|
ULONG DirInfoSize;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
BOOLEAN PassQueryDirectoryPattern, PatternIsFileName;
|
BOOLEAN PassQueryDirectoryPattern, PatternIsWild, PatternIsFileName;
|
||||||
BOOLEAN Success;
|
BOOLEAN Success;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
@ -520,6 +520,14 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if the pattern does not contain wildcards and we already returned a result, bail now! */
|
||||||
|
PatternIsWild = FsRtlDoesNameContainWildCards(&FileDesc->DirectoryPattern);
|
||||||
|
if (!PatternIsWild && FileDesc->DirectoryHasSuchFile)
|
||||||
|
{
|
||||||
|
FspFileNodeRelease(FileNode, Full);
|
||||||
|
return STATUS_NO_MORE_FILES;
|
||||||
|
}
|
||||||
|
|
||||||
/* see if the required information is still in the cache and valid! */
|
/* see if the required information is still in the cache and valid! */
|
||||||
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
if (FspFileNodeReferenceDirInfo(FileNode, &DirInfoBuffer, &DirInfoSize))
|
||||||
{
|
{
|
||||||
@ -545,19 +553,10 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
|||||||
|
|
||||||
/* special handling when pattern is filename */
|
/* special handling when pattern is filename */
|
||||||
PatternIsFileName = FsvolDeviceExtension->VolumeParams.PassQueryDirectoryFileName &&
|
PatternIsFileName = FsvolDeviceExtension->VolumeParams.PassQueryDirectoryFileName &&
|
||||||
!FsRtlDoesNameContainWildCards(&FileDesc->DirectoryPattern);
|
!PatternIsWild;
|
||||||
PassQueryDirectoryPattern = PatternIsFileName ||
|
PassQueryDirectoryPattern = PatternIsFileName ||
|
||||||
(FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
|
(FsvolDeviceExtension->VolumeParams.PassQueryDirectoryPattern &&
|
||||||
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer);
|
FspFileDescDirectoryPatternMatchAll != FileDesc->DirectoryPattern.Buffer);
|
||||||
if (PatternIsFileName &&
|
|
||||||
0 != FileDesc->DirectoryMarker.Buffer &&
|
|
||||||
0 == FspFileNameCompare(&FileDesc->DirectoryPattern, &FileDesc->DirectoryMarker,
|
|
||||||
!FileDesc->CaseSensitive, 0))
|
|
||||||
{
|
|
||||||
FspFileNodeRelease(FileNode, Full);
|
|
||||||
return !FileDesc->DirectoryHasSuchFile ?
|
|
||||||
STATUS_NO_SUCH_FILE : STATUS_NO_MORE_FILES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* probe and lock the user buffer */
|
/* probe and lock the user buffer */
|
||||||
Result = FspLockUserBuffer(Irp, Length, IoWriteAccess);
|
Result = FspLockUserBuffer(Irp, Length, IoWriteAccess);
|
||||||
|
@ -1497,6 +1497,7 @@ typedef struct
|
|||||||
DidSetFileAttributes:1, DidSetReparsePoint:1, DidSetSecurity:1,
|
DidSetFileAttributes:1, DidSetReparsePoint:1, DidSetSecurity:1,
|
||||||
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
DidSetCreationTime:1, DidSetLastAccessTime:1, DidSetLastWriteTime:1, DidSetChangeTime:1,
|
||||||
DirectoryHasSuchFile:1;
|
DirectoryHasSuchFile:1;
|
||||||
|
NTSTATUS DispositionStatus;
|
||||||
UNICODE_STRING DirectoryPattern;
|
UNICODE_STRING DirectoryPattern;
|
||||||
UNICODE_STRING DirectoryMarker;
|
UNICODE_STRING DirectoryMarker;
|
||||||
UINT64 DirInfo;
|
UINT64 DirInfo;
|
||||||
|
@ -83,6 +83,8 @@ static NTSTATUS FspFsvolSetDispositionInformation(
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolSetDispositionInformationSuccess(
|
static NTSTATUS FspFsvolSetDispositionInformationSuccess(
|
||||||
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
|
static NTSTATUS FspFsvolSetDispositionInformationFailure(
|
||||||
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
|
||||||
static NTSTATUS FspFsvolSetRenameInformation(
|
static NTSTATUS FspFsvolSetRenameInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||||
static NTSTATUS FspFsvolSetRenameInformationSuccess(
|
static NTSTATUS FspFsvolSetRenameInformationSuccess(
|
||||||
@ -125,6 +127,7 @@ FAST_IO_QUERY_OPEN FspFastIoQueryOpen;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolSetPositionInformation)
|
#pragma alloc_text(PAGE, FspFsvolSetPositionInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformation)
|
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformationSuccess)
|
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformationSuccess)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformationFailure)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetRenameInformation)
|
#pragma alloc_text(PAGE, FspFsvolSetRenameInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetRenameInformationSuccess)
|
#pragma alloc_text(PAGE, FspFsvolSetRenameInformationSuccess)
|
||||||
#pragma alloc_text(PAGE, FspFsvolSetInformation)
|
#pragma alloc_text(PAGE, FspFsvolSetInformation)
|
||||||
@ -1567,6 +1570,27 @@ retry:
|
|||||||
else
|
else
|
||||||
DispositionFlags = FILE_DISPOSITION_DO_NOT_DELETE;
|
DispositionFlags = FILE_DISPOSITION_DO_NOT_DELETE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DeleteFileW and RemoveDirectoryW in recent versions of Windows 10 have been changed to
|
||||||
|
* perform a FileDispositionInformationEx with POSIX semantics and if that fails to retry
|
||||||
|
* with FileDispositionInformation. Unfortunately this is done even for legitimate error
|
||||||
|
* codes such as STATUS_DIRECTORY_NOT_EMPTY.
|
||||||
|
*
|
||||||
|
* This means that user mode file systems have to do unnecessary CanDelete checks even when
|
||||||
|
* they support FileDispositionInformationEx. The extra check incurs extra context switches,
|
||||||
|
* and in some cases it may also be costly to compute (e.g. FUSE).
|
||||||
|
*
|
||||||
|
* We optimize this away by storing the status of the last CanDelete check in the FileDesc
|
||||||
|
* and then continue returning the same status code for all checks for the same FileDesc.
|
||||||
|
*/
|
||||||
|
if (FILE_DISPOSITION_DELETE == (DispositionFlags & ~FILE_DISPOSITION_POSIX_SEMANTICS) &&
|
||||||
|
STATUS_SUCCESS != FileDesc->DispositionStatus)
|
||||||
|
{
|
||||||
|
Result = FileDesc->DispositionStatus;
|
||||||
|
goto unlock_exit;
|
||||||
|
}
|
||||||
|
FileDesc->DispositionStatus = STATUS_SUCCESS;
|
||||||
|
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0,
|
||||||
FspFsvolSetInformationRequestFini, &Request);
|
FspFsvolSetInformationRequestFini, &Request);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -1629,6 +1653,44 @@ static NTSTATUS FspFsvolSetDispositionInformationSuccess(
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolSetDispositionInformationFailure(
|
||||||
|
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
FSP_FILE_DESC *FileDesc = FileObject->FsContext2;
|
||||||
|
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
|
||||||
|
UINT32 DispositionFlags = Request->Req.SetInformation.Info.DispositionEx.Flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DeleteFileW and RemoveDirectoryW in recent versions of Windows 10 have been changed to
|
||||||
|
* perform a FileDispositionInformationEx with POSIX semantics and if that fails to retry
|
||||||
|
* with FileDispositionInformation. Unfortunately this is done even for legitimate error
|
||||||
|
* codes such as STATUS_DIRECTORY_NOT_EMPTY.
|
||||||
|
*
|
||||||
|
* This means that user mode file systems have to do unnecessary CanDelete checks even when
|
||||||
|
* they support FileDispositionInformationEx. The extra check incurs extra context switches,
|
||||||
|
* and in some cases it may also be costly to compute (e.g. FUSE).
|
||||||
|
*
|
||||||
|
* We optimize this away by storing the status of the last CanDelete check in the FileDesc
|
||||||
|
* and then continue returning the same status code for all checks for the same FileDesc.
|
||||||
|
*/
|
||||||
|
switch (Response->IoStatus.Status)
|
||||||
|
{
|
||||||
|
case STATUS_ACCESS_DENIED:
|
||||||
|
case STATUS_DIRECTORY_NOT_EMPTY:
|
||||||
|
case STATUS_CANNOT_DELETE:
|
||||||
|
if (FILE_DISPOSITION_DELETE == (DispositionFlags & ~FILE_DISPOSITION_POSIX_SEMANTICS))
|
||||||
|
FileDesc->DispositionStatus = Response->IoStatus.Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
return Response->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolSetRenameInformation(
|
static NTSTATUS FspFsvolSetRenameInformation(
|
||||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
{
|
{
|
||||||
@ -2095,15 +2157,23 @@ NTSTATUS FspFsvolSetInformationComplete(
|
|||||||
{
|
{
|
||||||
FSP_ENTER_IOC(PAGED_CODE());
|
FSP_ENTER_IOC(PAGED_CODE());
|
||||||
|
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
||||||
|
|
||||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||||
{
|
{
|
||||||
|
/* special case FileDispositionInformation */
|
||||||
|
switch (FileInformationClass)
|
||||||
|
{
|
||||||
|
case FileDispositionInformation:
|
||||||
|
case FileDispositionInformationEx:
|
||||||
|
FSP_RETURN(Result = FspFsvolSetDispositionInformationFailure(Irp, Response));
|
||||||
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
Result = Response->IoStatus.Status;
|
Result = Response->IoStatus.Status;
|
||||||
FSP_RETURN();
|
FSP_RETURN();
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass;
|
|
||||||
|
|
||||||
/* special case FileDispositionInformation/FileRenameInformation */
|
/* special case FileDispositionInformation/FileRenameInformation */
|
||||||
switch (FileInformationClass)
|
switch (FileInformationClass)
|
||||||
{
|
{
|
||||||
|
@ -889,6 +889,10 @@ if X%5==XNOEXCL (
|
|||||||
-reparse* -stream* %~5
|
-reparse* -stream* %~5
|
||||||
)
|
)
|
||||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||||
|
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||||
|
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||||
|
+querydir_single_test
|
||||||
|
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||||
popd
|
popd
|
||||||
echo net use L: /delete
|
echo net use L: /delete
|
||||||
net use L: /delete
|
net use L: /delete
|
||||||
|
@ -376,6 +376,94 @@ static void dirbuf_fill_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dirbuf_boundary_dotest(PWSTR Marker, ULONG ExpectI, ULONG ExpectN, ...)
|
||||||
|
{
|
||||||
|
PVOID DirBuffer = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
BOOLEAN Success;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT8 B[sizeof(FSP_FSCTL_DIR_INFO) + MAX_PATH * sizeof(WCHAR)];
|
||||||
|
FSP_FSCTL_DIR_INFO D;
|
||||||
|
} DirInfoBuf;
|
||||||
|
FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D, *DirInfoEnd;
|
||||||
|
UINT8 Buffer[1024];
|
||||||
|
ULONG Length, BytesTransferred;
|
||||||
|
WCHAR CurrFileName[MAX_PATH];
|
||||||
|
ULONG N;
|
||||||
|
PWSTR Name;
|
||||||
|
va_list Names0, Names1;
|
||||||
|
|
||||||
|
va_start(Names0, ExpectN);
|
||||||
|
va_copy(Names1, Names0);
|
||||||
|
|
||||||
|
Length = sizeof Buffer;
|
||||||
|
|
||||||
|
Result = STATUS_UNSUCCESSFUL;
|
||||||
|
Success = FspFileSystemAcquireDirectoryBuffer(&DirBuffer, FALSE, &Result);
|
||||||
|
ASSERT(Success);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
|
||||||
|
while (0 != (Name = va_arg(Names0, PWSTR)))
|
||||||
|
{
|
||||||
|
memset(&DirInfoBuf, 0, sizeof DirInfoBuf);
|
||||||
|
DirInfo->Size = (UINT16)(sizeof(FSP_FSCTL_DIR_INFO) + wcslen(Name) * sizeof(WCHAR));
|
||||||
|
wcscpy_s(DirInfo->FileNameBuf, MAX_PATH, Name);
|
||||||
|
Success = FspFileSystemFillDirectoryBuffer(&DirBuffer, DirInfo, &Result);
|
||||||
|
ASSERT(Success);
|
||||||
|
ASSERT(STATUS_SUCCESS == Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspFileSystemReleaseDirectoryBuffer(&DirBuffer);
|
||||||
|
|
||||||
|
BytesTransferred = 0;
|
||||||
|
FspFileSystemReadDirectoryBuffer(&DirBuffer, Marker, Buffer, Length, &BytesTransferred);
|
||||||
|
|
||||||
|
for (N = 0; ExpectI > N; N++)
|
||||||
|
va_arg(Names1, PWSTR);
|
||||||
|
|
||||||
|
for (N = 0,
|
||||||
|
DirInfo = (PVOID)Buffer, DirInfoEnd = (PVOID)(Buffer + BytesTransferred);
|
||||||
|
DirInfoEnd > DirInfo && 0 != DirInfo->Size;
|
||||||
|
DirInfo = (PVOID)((PUINT8)DirInfo + FSP_FSCTL_DEFAULT_ALIGN_UP(DirInfo->Size)), N++)
|
||||||
|
{
|
||||||
|
memcpy(CurrFileName, DirInfo->FileNameBuf, DirInfo->Size - sizeof *DirInfo);
|
||||||
|
CurrFileName[(DirInfo->Size - sizeof *DirInfo) / sizeof(WCHAR)] = L'\0';
|
||||||
|
|
||||||
|
Name = va_arg(Names1, PWSTR);
|
||||||
|
ASSERT(0 == wcscmp(CurrFileName, Name));
|
||||||
|
}
|
||||||
|
ASSERT(ExpectN == N);
|
||||||
|
|
||||||
|
FspFileSystemDeleteDirectoryBuffer(&DirBuffer);
|
||||||
|
|
||||||
|
va_end(Names1);
|
||||||
|
va_end(Names0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dirbuf_boundary_test(void)
|
||||||
|
{
|
||||||
|
dirbuf_boundary_dotest(L"A", 0, 0, 0);
|
||||||
|
|
||||||
|
dirbuf_boundary_dotest(L"A", 0, 1, L"B", 0);
|
||||||
|
dirbuf_boundary_dotest(L"B", 0, 0, L"B", 0);
|
||||||
|
dirbuf_boundary_dotest(L"C", 0, 0, L"B", 0);
|
||||||
|
|
||||||
|
dirbuf_boundary_dotest(L"A", 0, 2, L"B", L"D", 0);
|
||||||
|
dirbuf_boundary_dotest(L"B", 1, 1, L"B", L"D", 0);
|
||||||
|
dirbuf_boundary_dotest(L"C", 1, 1, L"B", L"D", 0);
|
||||||
|
dirbuf_boundary_dotest(L"D", 0, 0, L"B", L"D", 0);
|
||||||
|
dirbuf_boundary_dotest(L"E", 0, 0, L"B", L"D", 0);
|
||||||
|
|
||||||
|
dirbuf_boundary_dotest(L"A", 0, 3, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"B", 1, 2, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"C", 1, 2, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"D", 2, 1, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"E", 2, 1, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"F", 0, 0, L"B", L"D", L"F", 0);
|
||||||
|
dirbuf_boundary_dotest(L"G", 0, 0, L"B", L"D", L"F", 0);
|
||||||
|
}
|
||||||
|
|
||||||
void dirbuf_tests(void)
|
void dirbuf_tests(void)
|
||||||
{
|
{
|
||||||
if (OptExternal)
|
if (OptExternal)
|
||||||
@ -384,4 +472,5 @@ void dirbuf_tests(void)
|
|||||||
TEST(dirbuf_empty_test);
|
TEST(dirbuf_empty_test);
|
||||||
TEST(dirbuf_dots_test);
|
TEST(dirbuf_dots_test);
|
||||||
TEST(dirbuf_fill_test);
|
TEST(dirbuf_fill_test);
|
||||||
|
TEST(dirbuf_boundary_test);
|
||||||
}
|
}
|
||||||
|
@ -269,6 +269,93 @@ void querydir_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void querydir_single_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
WCHAR CurrentDirectory[MAX_PATH], FileName[MAX_PATH];
|
||||||
|
WIN32_FIND_DATAW FindData;
|
||||||
|
|
||||||
|
StringCbPrintfW(FileName, sizeof FileName, L"%s%s\\",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
Success = GetCurrentDirectoryW(MAX_PATH, CurrentDirectory);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
Success = SetCurrentDirectoryW(FileName);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (ULONG Index = 0; 1000 > Index; Index++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FileName, sizeof FileName, L"xxxxxxx-file%lu", Index);
|
||||||
|
Handle = CreateFileW(FileName,
|
||||||
|
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
0,
|
||||||
|
CREATE_NEW, FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = FindFirstFileW(L"*", &FindData);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
} while (FindNextFileW(Handle, &FindData));
|
||||||
|
Success = FindClose(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (ULONG Index = 0; 1000 > Index; Index++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FileName, sizeof FileName, L"xxxxxxx-file%lu", Index);
|
||||||
|
Handle = FindFirstFileW(FileName, &FindData);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
} while (FindNextFileW(Handle, &FindData));
|
||||||
|
Success = FindClose(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ULONG Index = 0; 1000 > Index; Index++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FileName, sizeof FileName, L"xxxxxxx-file%lu", Index);
|
||||||
|
Success = DeleteFileW(FileName);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
Success = RealSetCurrentDirectoryW(CurrentDirectory);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void querydir_single_test(void)
|
||||||
|
{
|
||||||
|
if (OptShareName)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (NtfsTests)
|
||||||
|
{
|
||||||
|
WCHAR DirBuf[MAX_PATH];
|
||||||
|
GetTestDirectory(DirBuf);
|
||||||
|
querydir_single_dotest(-1, DirBuf, 0, 0);
|
||||||
|
}
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
{
|
||||||
|
querydir_single_dotest(MemfsDisk, 0, 0, 0);
|
||||||
|
querydir_single_dotest(MemfsDisk, 0, 1000, 0);
|
||||||
|
}
|
||||||
|
if (WinFspNetTests)
|
||||||
|
{
|
||||||
|
querydir_single_dotest(MemfsNet, L"\\\\memfs\\share", 0, 0);
|
||||||
|
querydir_single_dotest(MemfsNet, L"\\\\memfs\\share", 1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void querydir_expire_cache_test(void)
|
void querydir_expire_cache_test(void)
|
||||||
{
|
{
|
||||||
if (WinFspDiskTests)
|
if (WinFspDiskTests)
|
||||||
@ -645,6 +732,8 @@ void dirnotify_test(void)
|
|||||||
void dirctl_tests(void)
|
void dirctl_tests(void)
|
||||||
{
|
{
|
||||||
TEST(querydir_test);
|
TEST(querydir_test);
|
||||||
|
if (!OptShareName)
|
||||||
|
TEST_OPT(querydir_single_test);
|
||||||
TEST(querydir_expire_cache_test);
|
TEST(querydir_expire_cache_test);
|
||||||
if (!OptShareName)
|
if (!OptShareName)
|
||||||
TEST(querydir_buffer_overflow_test);
|
TEST(querydir_buffer_overflow_test);
|
||||||
|
@ -50,7 +50,7 @@ static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf)
|
|||||||
else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
|
else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
|
||||||
P = FileNameBuf + 2;
|
P = FileNameBuf + 2;
|
||||||
else
|
else
|
||||||
ABORT("unknown filename format");
|
P = FileNameBuf;
|
||||||
|
|
||||||
for (EndP = P + wcslen(P); EndP > P; P++)
|
for (EndP = P + wcslen(P); EndP > P; P++)
|
||||||
if (testalpha(*P) && myrand() <= (TogglePercent) * 0x7fff / 100)
|
if (testalpha(*P) && myrand() <= (TogglePercent) * 0x7fff / 100)
|
||||||
@ -71,7 +71,7 @@ static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf)
|
|||||||
else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
|
else if (testalpha(FileNameBuf[0]) && L':' == FileNameBuf[1] && L'\\' == FileNameBuf[2])
|
||||||
ABORT("--mountpoint not supported with NTFS");
|
ABORT("--mountpoint not supported with NTFS");
|
||||||
else
|
else
|
||||||
ABORT("unknown filename format");
|
P = FileNameBuf;
|
||||||
|
|
||||||
L1 = wcslen(P) + 1;
|
L1 = wcslen(P) + 1;
|
||||||
L2 = wcslen(OptMountPoint);
|
L2 = wcslen(OptMountPoint);
|
||||||
@ -96,7 +96,7 @@ static VOID PrepareFileName(PCWSTR FileName, PWSTR FileNameBuf)
|
|||||||
/* NTFS testing can only been done when the whole drive is being shared */
|
/* NTFS testing can only been done when the whole drive is being shared */
|
||||||
P = FileNameBuf + 2;
|
P = FileNameBuf + 2;
|
||||||
else
|
else
|
||||||
ABORT("unknown filename format");
|
P = FileNameBuf;
|
||||||
|
|
||||||
L1 = wcslen(P) + 1;
|
L1 = wcslen(P) + 1;
|
||||||
L2 = wcslen(OptShareComputer);
|
L2 = wcslen(OptShareComputer);
|
||||||
|
Reference in New Issue
Block a user