mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
2fb2de067c | |||
423c70757c | |||
551ed341a7 | |||
52ffb47fee | |||
c208e0ecbd | |||
87389f010b | |||
c32b1c19c2 | |||
8ce6836674 |
@ -1,6 +1,90 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v1.10 (2022)::
|
||||||
|
|
||||||
|
Changes since v1.9:
|
||||||
|
|
||||||
|
* [NEW] Official Windows 11 support.
|
||||||
|
|
||||||
|
* [NEW] Support for `FileDispositionInformationEx` and `FileRenameInformationEx` has been added. Native and .NET file systems must enable this support by setting `SupportsPosixUnlinkRename` in `FSP_FSCTL_VOLUME_PARAMS`. FUSE file systems have this support enabled by default, but they can disable it by using the `-o LegacyUnlinkRename` command line option.
|
||||||
|
|
||||||
|
* [NEW] WinFsp now supports rebranding of the build products. This is primarily useful to commercial licensees. See https://github.com/billziss-gh/winfsp/wiki/WinFsp-Rebranding for more information.
|
||||||
|
|
||||||
|
* [NEW] WinFsp-FUSE has a new capability `FSP_FUSE_CAP_DELETE_ACCESS`. If this capability is specified WinFsp will call the FUSE `access` method with the WinFsp-specific flag `FSP_FUSE_DELETE_OK` to check whether the deletion should be allowed. This can be used to disallow deletion of files and directories that would normally be allowed under the FUSE/POSIX model.
|
||||||
|
|
||||||
|
* [NEW] WinFsp-FUSE has a new method for determining file access in the case where the user's primary SID (Windows Security Identifier) and group SID are the same (for example, this can happen when someone uses a Microsoft account as their primary login).
|
||||||
|
** Previously when the user SID and group SID were the same WinFsp-FUSE looked at the UNIX permissions for the owner and the UNIX permissions for the group and used the MOST restrictive permissions, which often resulted in inadvertent "access denied" errors. (For example, if the owner permission was `rw-` and the group permission was `---` the result was `---` and therefore access denied).
|
||||||
|
** Going forward this behavior will change. The user and group mode permissions will not be considered together even in the case where the user SID and group SID are the same. This will resolve the access denied errors.
|
||||||
|
** However to preserve backward compatibility (there might be some file systems that rely on the old behavior) we will do so in stages. For release v1.10 (2021.1) there is a new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `DistinctPermsForSameOwnerGroup`, which if set to 1 will direct WinFsp-FUSE to use the new behavior. The default value is 0 which directs WinFsp-FUSE to use the old behavior. This default will change in a future release.
|
||||||
|
|
||||||
|
* [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountDoNotUseLauncher` has been introduced, which if set to 1 will disable the use of the Launcher during mounting. The default value is 0 which allows the use of the Launcher during mounting in those rare cases when necessary. (In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.)
|
||||||
|
|
||||||
|
* [NEW] A new sample memfs-fuse file system written in C++ has been added. This file system uses all FUSE2 features offered by WinFsp-FUSE, passes all file system tests (that can be passed by a FUSE2 file system) and will act as the reference WinFsp-FUSE file system going forward.
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem with `FspFileSystemReadDirectoryBuffer` and file systems that support pattern matching (like passthrough). (GitHub issue #351.)
|
||||||
|
|
||||||
|
* [FIX] File share access when overwriting a file (e.g. when using `TRUNCATE_EXISTING`) is now done in a manner compatible with NTFS (previously there were cases when overwriting a file where behavior diverged from the NTFS one). (See GitHub issue #364.)
|
||||||
|
|
||||||
|
* [FIX] The FSD will now report a file's reparse tag in the `EaSize` field of `FILE_FULL_DIR_INFORMATION` and friends. This fixes problems such as `cmd.exe` not recognizing symlinks in a `dir` command. (See GitHub issue #380.)
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem in the file system shutdown protocol which resolves an occasional access violation in the user mode file system process. Previously it was possible for a file system to crash when stopping itself using `FspFileSystemStopDispatcher`; this problem has been rectified. (See GitHub issue #369.)
|
||||||
|
|
||||||
|
* [FIX] Improved symlink support for FUSE file systems. Notably:
|
||||||
|
|
||||||
|
** FUSE file systems now support converting a directory to a symlink reparse point.
|
||||||
|
|
||||||
|
** The determination of whether a symlink is a file or directory (necessary because the Windows file system makes this distinction) is now possible for file systems that do not support slashdot (`/.`) queries. (A slashdot query is one like `getattr("/PATH/.")`; such queries are not normally expected to be resolved by FUSE file systems.)
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem in the FUSE layer where in some rare circumstances the `release` operation could be called with an uninitialized `path` argument. (See GitHub issue billziss-gh/cgofuse#58 and commit f51bdef53427d1bba688fb6c768792fdc22ffc7b).
|
||||||
|
|
||||||
|
* [FIX] Fixed a potential problem when launching file system instances using the Launcher. (See GitHub issue #356.)
|
||||||
|
|
||||||
|
* [FIX] The `winfsp.h` header no longer defines `FILE_FULL_EA_INFORMATION` when compiled under mingw. This is because the mingw tool chain already includes a definition of this type. (GitHub PR #371. Thanks @ lemourin.)
|
||||||
|
|
||||||
|
|
||||||
|
v1.10B5 (2022 Beta5)::
|
||||||
|
|
||||||
|
Changes since v1.9:
|
||||||
|
|
||||||
|
* [NEW] Official Windows 11 support.
|
||||||
|
|
||||||
|
* [NEW] Support for `FileDispositionInformationEx` and `FileRenameInformationEx` has been added. Native and .NET file systems must enable this support by setting `SupportsPosixUnlinkRename` in `FSP_FSCTL_VOLUME_PARAMS`. FUSE file systems have this support enabled by default, but they can disable it by using the `-o LegacyUnlinkRename` command line option.
|
||||||
|
|
||||||
|
* [NEW] WinFsp now supports rebranding of the build products. This is primarily useful to commercial licensees. See https://github.com/billziss-gh/winfsp/wiki/WinFsp-Rebranding for more information.
|
||||||
|
|
||||||
|
* [NEW] WinFsp-FUSE has a new capability `FSP_FUSE_CAP_DELETE_ACCESS`. If this capability is specified WinFsp will call the FUSE `access` method with the WinFsp-specific flag `FSP_FUSE_DELETE_OK` to check whether the deletion should be allowed. This can be used to disallow deletion of files and directories that would normally be allowed under the FUSE/POSIX model.
|
||||||
|
|
||||||
|
* [NEW] WinFsp-FUSE has a new method for determining file access in the case where the user's primary SID (Windows Security Identifier) and group SID are the same (for example, this can happen when someone uses a Microsoft account as their primary login).
|
||||||
|
** Previously when the user SID and group SID were the same WinFsp-FUSE looked at the UNIX permissions for the owner and the UNIX permissions for the group and used the MOST restrictive permissions, which often resulted in inadvertent "access denied" errors. (For example, if the owner permission was `rw-` and the group permission was `---` the result was `---` and therefore access denied).
|
||||||
|
** Going forward this behavior will change. The user and group mode permissions will not be considered together even in the case where the user SID and group SID are the same. This will resolve the access denied errors.
|
||||||
|
** However to preserve backward compatibility (there might be some file systems that rely on the old behavior) we will do so in stages. For release v1.10 (2021.1) there is a new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `DistinctPermsForSameOwnerGroup`, which if set to 1 will direct WinFsp-FUSE to use the new behavior. The default value is 0 which directs WinFsp-FUSE to use the old behavior. This default will change in a future release.
|
||||||
|
|
||||||
|
* [NEW] A new registry setting under `HKLM\SOFTWARE\WinFsp` (or `HKLM\SOFTWARE\WOW6432Node\WinFsp` on a 64-bit system) called `MountDoNotUseLauncher` has been introduced, which if set to 1 will disable the use of the Launcher during mounting. The default value is 0 which allows the use of the Launcher during mounting in those rare cases when necessary. (In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.)
|
||||||
|
|
||||||
|
* [NEW] A new sample memfs-fuse file system written in C++ has been added. This file system uses all FUSE2 features offered by WinFsp-FUSE, passes all file system tests (that can be passed by a FUSE2 file system) and will act as the reference WinFsp-FUSE file system going forward.
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem with `FspFileSystemReadDirectoryBuffer` and file systems that support pattern matching (like passthrough). (GitHub issue #351.)
|
||||||
|
|
||||||
|
* [FIX] File share access when overwriting a file (e.g. when using `TRUNCATE_EXISTING`) is now done in a manner compatible with NTFS (previously there were cases when overwriting a file where behavior diverged from the NTFS one). (See GitHub issue #364.)
|
||||||
|
|
||||||
|
* [FIX] The FSD will now report a file's reparse tag in the `EaSize` field of `FILE_FULL_DIR_INFORMATION` and friends. This fixes problems such as `cmd.exe` not recognizing symlinks in a `dir` command. (See GitHub issue #380.)
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem in the file system shutdown protocol which resolves an occasional access violation in the user mode file system process. Previously it was possible for a file system to crash when stopping itself using `FspFileSystemStopDispatcher`; this problem has been rectified. (See GitHub issue #369.)
|
||||||
|
|
||||||
|
* [FIX] Improved symlink support for FUSE file systems. Notably:
|
||||||
|
|
||||||
|
** FUSE file systems now support converting a directory to a symlink reparse point.
|
||||||
|
|
||||||
|
** The determination of whether a symlink is a file or directory (necessary because the Windows file system makes this distinction) is now possible for file systems that do not support slashdot (`/.`) queries. (A slashdot query is one like `getattr("/PATH/.")`; such queries are not normally expected to be resolved by FUSE file systems.)
|
||||||
|
|
||||||
|
* [FIX] Fixed a problem in the FUSE layer where in some rare circumstances the `release` operation could be called with an uninitialized `path` argument. (See GitHub issue billziss-gh/cgofuse#58 and commit f51bdef53427d1bba688fb6c768792fdc22ffc7b).
|
||||||
|
|
||||||
|
* [FIX] Fixed a potential problem when launching file system instances using the Launcher. (See GitHub issue #356.)
|
||||||
|
|
||||||
|
* [FIX] The `winfsp.h` header no longer defines `FILE_FULL_EA_INFORMATION` when compiled under mingw. This is because the mingw tool chain already includes a definition of this type. (GitHub PR #371. Thanks @ lemourin.)
|
||||||
|
|
||||||
|
|
||||||
v1.10B4 (2022 Beta4)::
|
v1.10B4 (2022 Beta4)::
|
||||||
+
|
+
|
||||||
--
|
--
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
<MyCanonicalVersion>1.10</MyCanonicalVersion>
|
<MyCanonicalVersion>1.10</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2022 Beta4</MyProductVersion>
|
<MyProductVersion>2022</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>Gold</MyProductStage>
|
||||||
|
|
||||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
@ -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