mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 09:22:57 -05:00
Compare commits
14 Commits
v1.2B3
...
release/1.
Author | SHA1 | Date | |
---|---|---|---|
2a3eabfab2 | |||
35255526d3 | |||
b2e474658d | |||
a2ec40008f | |||
f3819ba839 | |||
ead599e337 | |||
eb88f25f40 | |||
c2b066a054 | |||
266e0f4bab | |||
d02030897d | |||
c87ff75b8f | |||
2ca33665ef | |||
391dcf8a21 | |||
69d68eb22f |
@ -1,6 +1,32 @@
|
||||
= Changelog
|
||||
|
||||
|
||||
v1.2POST1 (2017.2; issue #127)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
||||
- WinFsp-FUSE now supports BSD flags (Windows file attributes) during `getattr` and `fgetattr`. It also adds the `chflags` operation. BSD flags support requires use of the `FSP_FUSE_CAP_STAT_EX` capability and the new `struct fuse_stat_ex` which includes an `st_flags` field. If the preprocessor macro `FSP_FUSE_USE_STAT_EX` is defined before inclusion of `<fuse.h>` then `struct fuse_stat` will also be defined to include the `st_flags` field.
|
||||
- WinFsp-FUSE also adds the following OSXFUSE operations: `setcrtime`, `setchgtime`. These can be used to set the creation (birth) time and change (ctime) time of a file.
|
||||
- New `GetDirInfoByName` file system operation adds fast queries of directory info by file name rather than pattern [e.g. `FindFirstFileW(L"foobar", FindData)`]. Tests with fsbench showed that such queries are sped up by an order of magnitude when using `GetDirInfoByName` in MEMFS. Case-sensitive FUSE file systems get this optimization for free. The .NET layer also adds `GetDirInfoByName`.
|
||||
- New `FspFileSystemOperationProcessId` API adds support for getting the originating process ID (PID) during `Create`, `Open` and `Rename` calls. FUSE file systems can now access `fuse_context::pid`. The .NET layer also adds `GetOperationProcessId`.
|
||||
- New command line tool `fsptool` allows command line access to some WinFsp features.
|
||||
- The WinFsp launcher now passes the name of the user who launched the file system as a special parameter %U. This is useful to file systems that use the launcher infrastructure, such as SSHFS-Win. [Please note that in earlier betas the user name was passed as parameter %3; the previous method was insecure and is no longer supported.]
|
||||
- Important GitHub issues fixed: #96, #97, #103, #107, #127
|
||||
|
||||
|
||||
v1.2 (2017.2)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
||||
- WinFsp-FUSE now supports BSD flags (Windows file attributes) during `getattr` and `fgetattr`. It also adds the `chflags` operation. BSD flags support requires use of the `FSP_FUSE_CAP_STAT_EX` capability and the new `struct fuse_stat_ex` which includes an `st_flags` field. If the preprocessor macro `FSP_FUSE_USE_STAT_EX` is defined before inclusion of `<fuse.h>` then `struct fuse_stat` will also be defined to include the `st_flags` field.
|
||||
- WinFsp-FUSE also adds the following OSXFUSE operations: `setcrtime`, `setchgtime`. These can be used to set the creation (birth) time and change (ctime) time of a file.
|
||||
- New `GetDirInfoByName` file system operation adds fast queries of directory info by file name rather than pattern [e.g. `FindFirstFileW(L"foobar", FindData)`]. Tests with fsbench showed that such queries are sped up by an order of magnitude when using `GetDirInfoByName` in MEMFS. Case-sensitive FUSE file systems get this optimization for free. The .NET layer also adds `GetDirInfoByName`.
|
||||
- New `FspFileSystemOperationProcessId` API adds support for getting the originating process ID (PID) during `Create`, `Open` and `Rename` calls. FUSE file systems can now access `fuse_context::pid`. The .NET layer also adds `GetOperationProcessId`.
|
||||
- New command line tool `fsptool` allows command line access to some WinFsp features.
|
||||
- The WinFsp launcher now passes the name of the user who launched the file system as a special parameter %U. This is useful to file systems that use the launcher infrastructure, such as SSHFS-Win. [Please note that in earlier betas the user name was passed as parameter %3; the previous method was insecure and is no longer supported.]
|
||||
- Important GitHub issues fixed: #96, #97, #103, #107
|
||||
|
||||
|
||||
v1.2B3 (2017.2 B3)::
|
||||
|
||||
Changes since v1.1:
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
<MyCanonicalVersion>1.2</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2017.2 B3</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
<MyProductVersion>2017.2</MyProductVersion>
|
||||
<MyProductStage>Gold</MyProductStage>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||
|
@ -28,7 +28,7 @@ if ($key.Count -eq 1) {
|
||||
-File "$file"
|
||||
}
|
||||
} elseif ($key.Count -eq 0) {
|
||||
Write-Warning "$packageName has already been uninstalled by other means."
|
||||
# Write-Warning "$packageName is not installed"
|
||||
} elseif ($key.Count -gt 1) {
|
||||
Write-Warning "Too many matching packages found! Package may not be uninstalled."
|
||||
Write-Warning "Please alert package maintainer the following packages were matched:"
|
@ -1,16 +1,14 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
$fileLocation = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
. "$toolsdir\chocolateyHelper.ps1"
|
||||
|
||||
$packageArgs = @{
|
||||
packageName = 'winfsp'
|
||||
fileType = 'msi'
|
||||
file = $fileLocation
|
||||
file = @(Get-ChildItem $toolsDir -filter winfsp-*.msi)[0].FullName
|
||||
silentArgs = "/qn /norestart INSTALLLEVEL=1000"
|
||||
validExitCodes = @(0, 3010, 1641)
|
||||
}
|
||||
|
||||
Install-ChocolateyInstallPackage @packageArgs
|
||||
|
||||
Remove-Item -Force $packageArgs.file
|
||||
|
4
build/choco/chocolateyUninstall.ps1
Normal file
4
build/choco/chocolateyUninstall.ps1
Normal file
@ -0,0 +1,4 @@
|
||||
$ErrorActionPreference = 'Stop';
|
||||
|
||||
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
|
||||
. "$toolsdir\chocolateyHelper.ps1"
|
@ -50,7 +50,8 @@ To verify installation:
|
||||
<file src="LICENSE.txt" target="tools" />
|
||||
<file src="VERIFICATION.txt" target="tools" />
|
||||
<file src="chocolateyInstall.ps1" target="tools" />
|
||||
<file src="chocolateyBeforeModify.ps1" target="tools" />
|
||||
<file src="chocolateyUninstall.ps1" target="tools" />
|
||||
<file src="chocolateyHelper.ps1" target="tools" />
|
||||
<file src="winfsp-$version$.msi" target="tools" />
|
||||
</files>
|
||||
</package>
|
||||
|
@ -765,9 +765,9 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
memset(&fi, 0, sizeof fi);
|
||||
if ('C' == f->env->environment) /* Cygwin */
|
||||
fi.flags = 0x0200 | 2 /*O_CREAT|O_RDWR*/;
|
||||
fi.flags = 0x0200 | 0x0800 | 2 /*O_CREAT|O_EXCL|O_RDWR*/;
|
||||
else
|
||||
fi.flags = 0x0100 | 2 /*O_CREAT|O_RDWR*/;
|
||||
fi.flags = 0x0100 | 0x0400 | 2 /*O_CREAT|O_EXCL|O_RDWR*/;
|
||||
|
||||
if (CreateOptions & FILE_DIRECTORY_FILE)
|
||||
{
|
||||
@ -821,16 +821,25 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
Opened = TRUE;
|
||||
|
||||
if (Uid != context->uid || Gid != context->gid)
|
||||
if (0 != f->ops.chown)
|
||||
{
|
||||
err = f->ops.chown(contexthdr->PosixPath, Uid, Gid);
|
||||
if (0 != err)
|
||||
{
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (0 != FileAttributes &&
|
||||
0 != (f->conn_want & FSP_FUSE_CAP_STAT_EX) && 0 != f->ops.chflags)
|
||||
{
|
||||
err = f->ops.chflags(contexthdr->PosixPath,
|
||||
fsp_fuse_intf_MapFileAttributesToFlags(CreateOptions & FILE_DIRECTORY_FILE ?
|
||||
FileAttributes : FileAttributes | FILE_ATTRIBUTE_ARCHIVE));
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((Uid != context->uid || Gid != context->gid) &&
|
||||
0 != f->ops.chown)
|
||||
{
|
||||
err = f->ops.chown(contexthdr->PosixPath, Uid, Gid);
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignore fuse_file_info::direct_io, fuse_file_info::keep_cache.
|
||||
@ -1015,6 +1024,22 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
if (0 != FileAttributes &&
|
||||
0 != (f->conn_want & FSP_FUSE_CAP_STAT_EX) && 0 != f->ops.chflags)
|
||||
{
|
||||
/*
|
||||
* The code below is not strictly correct. File attributes should be
|
||||
* replaced when ReplaceFileAttributes is TRUE and merged (or'ed) when
|
||||
* ReplaceFileAttributes is FALSE. I am punting on this detail for now.
|
||||
*/
|
||||
|
||||
err = f->ops.chflags(filedesc->PosixPath,
|
||||
fsp_fuse_intf_MapFileAttributesToFlags(FileAttributes | FILE_ATTRIBUTE_ARCHIVE));
|
||||
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
return Result;
|
||||
}
|
||||
|
||||
return fsp_fuse_intf_GetFileInfoEx(FileSystem, filedesc->PosixPath, &fi,
|
||||
&Uid, &Gid, &Mode, FileInfo);
|
||||
}
|
||||
|
12
src/dll/np.c
12
src/dll/np.c
@ -17,7 +17,6 @@
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <launcher/launcher.h>
|
||||
#include <lmcons.h>
|
||||
#include <npapi.h>
|
||||
#include <wincred.h>
|
||||
|
||||
@ -169,12 +168,6 @@ static inline BOOLEAN FspNpParseRemoteUserName(PWSTR RemoteName,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline BOOLEAN FspNpGetLocalUserName(
|
||||
PWSTR UserName, ULONG UserNameSize/* in chars */)
|
||||
{
|
||||
return GetUserName(UserName, &UserNameSize);
|
||||
}
|
||||
|
||||
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||
{
|
||||
DWORD NpResult;
|
||||
@ -496,7 +489,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
WCHAR LocalNameBuf[3];
|
||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||
ULONG ClassNameLen, InstanceNameLen;
|
||||
WCHAR LocalUserName[UNLEN + 1];
|
||||
DWORD CredentialsKind;
|
||||
PWSTR PipeBuf = 0;
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
@ -525,9 +517,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
return WN_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
if (!FspNpGetLocalUserName(LocalUserName, sizeof LocalUserName / sizeof LocalUserName[0]))
|
||||
LocalUserName[0] = L'\0';
|
||||
|
||||
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||
|
||||
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||
@ -582,7 +571,6 @@ DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword,
|
||||
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
||||
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
||||
lstrcpyW(P, LocalUserName); P += lstrlenW(LocalUserName) + 1;
|
||||
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||
{
|
||||
lstrcpyW(P, lpUserName); P += lstrlenW(lpUserName) + 1;
|
||||
|
@ -21,12 +21,16 @@
|
||||
#define PROGNAME "WinFsp.Launcher"
|
||||
|
||||
BOOL CreateOverlappedPipe(
|
||||
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||
PHANDLE PReadPipe, PHANDLE PWritePipe,
|
||||
DWORD Size,
|
||||
BOOL ReadInherit, BOOL WriteInherit,
|
||||
DWORD ReadMode, DWORD WriteMode)
|
||||
{
|
||||
RPC_STATUS RpcStatus;
|
||||
UUID Uuid;
|
||||
WCHAR PipeNameBuf[MAX_PATH];
|
||||
SECURITY_ATTRIBUTES ReadSecurityAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, ReadInherit };
|
||||
SECURITY_ATTRIBUTES WriteSecurityAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, WriteInherit };
|
||||
HANDLE ReadPipe, WritePipe;
|
||||
DWORD LastError;
|
||||
|
||||
@ -46,13 +50,13 @@ BOOL CreateOverlappedPipe(
|
||||
ReadPipe = CreateNamedPipeW(PipeNameBuf,
|
||||
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||
1, Size, Size, 120 * 1000, SecurityAttributes);
|
||||
1, Size, Size, 120 * 1000, &ReadSecurityAttributes);
|
||||
if (INVALID_HANDLE_VALUE == ReadPipe)
|
||||
return FALSE;
|
||||
|
||||
WritePipe = CreateFileW(PipeNameBuf,
|
||||
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||
&WriteSecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||
if (INVALID_HANDLE_VALUE == WritePipe)
|
||||
{
|
||||
LastError = GetLastError();
|
||||
@ -67,6 +71,76 @@ BOOL CreateOverlappedPipe(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS GetTokenUserName(HANDLE Token, PWSTR *PUserName)
|
||||
{
|
||||
TOKEN_USER *User = 0;
|
||||
WCHAR Name[256], Domn[256];
|
||||
DWORD UserSize, NameSize, DomnSize;
|
||||
SID_NAME_USE Use;
|
||||
PWSTR P;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PUserName = 0;
|
||||
|
||||
if (GetTokenInformation(Token, TokenUser, 0, 0, &UserSize))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
User = MemAlloc(UserSize);
|
||||
if (0 == User)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, User, UserSize, &UserSize))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
NameSize = sizeof Name / sizeof Name[0];
|
||||
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||
if (!LookupAccountSidW(0, User->User.Sid, Name, &NameSize, Domn, &DomnSize, &Use))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
NameSize = lstrlenW(Name);
|
||||
DomnSize = lstrlenW(Domn);
|
||||
|
||||
P = *PUserName = MemAlloc((DomnSize + 1 + NameSize + 1) * sizeof(WCHAR));
|
||||
if (0 == P)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 < DomnSize)
|
||||
{
|
||||
memcpy(P, Domn, DomnSize * sizeof(WCHAR));
|
||||
P[DomnSize] = L'\\';
|
||||
P += DomnSize + 1;
|
||||
}
|
||||
memcpy(P, Name, NameSize * sizeof(WCHAR));
|
||||
P[NameSize] = L'\0';
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(User);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
HANDLE Process;
|
||||
@ -142,6 +216,17 @@ typedef struct
|
||||
static CRITICAL_SECTION SvcInstanceLock;
|
||||
static HANDLE SvcInstanceEvent;
|
||||
static LIST_ENTRY SvcInstanceList = { &SvcInstanceList, &SvcInstanceList };
|
||||
static DWORD SvcInstanceTlsKey = TLS_OUT_OF_INDEXES;
|
||||
|
||||
static inline PWSTR SvcInstanceUserName(VOID)
|
||||
{
|
||||
return TlsGetValue(SvcInstanceTlsKey);
|
||||
}
|
||||
|
||||
static inline VOID SvcInstanceSetUserName(PWSTR UserName)
|
||||
{
|
||||
TlsSetValue(SvcInstanceTlsKey, UserName);
|
||||
}
|
||||
|
||||
static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout);
|
||||
|
||||
@ -210,6 +295,14 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
||||
else
|
||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
||||
}
|
||||
else
|
||||
if (L'U' == *P)
|
||||
{
|
||||
if (0 != SvcInstanceUserName())
|
||||
Length += SvcInstanceArgumentLength(SvcInstanceUserName());
|
||||
else
|
||||
Length += SvcInstanceArgumentLength(EmptyArg);
|
||||
}
|
||||
else
|
||||
Length++;
|
||||
break;
|
||||
@ -236,6 +329,14 @@ static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Arg
|
||||
else
|
||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
||||
}
|
||||
else
|
||||
if (L'U' == *P)
|
||||
{
|
||||
if (0 != SvcInstanceUserName())
|
||||
Q = SvcInstanceArgumentCopy(Q, SvcInstanceUserName());
|
||||
else
|
||||
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
||||
}
|
||||
else
|
||||
*Q++ = *P;
|
||||
break;
|
||||
@ -286,7 +387,6 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
STARTUPINFOEXW StartupInfoEx;
|
||||
HANDLE ChildHandles[3] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0/* DO NOT CLOSE!*/ };
|
||||
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
|
||||
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
|
||||
SIZE_T Size;
|
||||
NTSTATUS Result;
|
||||
@ -304,16 +404,16 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
*/
|
||||
|
||||
/* create stdin read/write ends; make them inheritable */
|
||||
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
|
||||
0, 0))
|
||||
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0],
|
||||
0, TRUE, FALSE, 0, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* create stdout read/write ends; make them inheritable */
|
||||
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
|
||||
FILE_FLAG_OVERLAPPED, 0))
|
||||
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1],
|
||||
0, FALSE, TRUE, FILE_FLAG_OVERLAPPED, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
@ -361,8 +461,28 @@ NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
|
||||
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
if (ERROR_NO_SYSTEM_RESOURCES != GetLastError())
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* On Win7 CreateProcessW with EXTENDED_STARTUPINFO_PRESENT
|
||||
* may fail with ERROR_NO_SYSTEM_RESOURCES.
|
||||
*
|
||||
* In that case go ahead and retry with a CreateProcessW with
|
||||
* bInheritHandles==TRUE, but without EXTENDED_STARTUPINFO_PRESENT.
|
||||
* Not ideal, but...
|
||||
*/
|
||||
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
|
||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
|
||||
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -752,6 +872,10 @@ exit:
|
||||
|
||||
SvcInstanceRelease(SvcInstance);
|
||||
|
||||
if (STATUS_TIMEOUT == Result)
|
||||
/* convert to an error! */
|
||||
Result = 0x80070000 | ERROR_TIMEOUT;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -918,6 +1042,10 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||
if (0 == SvcInstanceEvent)
|
||||
goto fail;
|
||||
|
||||
SvcInstanceTlsKey = TlsAlloc();
|
||||
if (TLS_OUT_OF_INDEXES == SvcInstanceTlsKey)
|
||||
goto fail;
|
||||
|
||||
SvcJob = CreateJobObjectW(0, 0);
|
||||
if (0 != SvcJob)
|
||||
{
|
||||
@ -980,6 +1108,9 @@ fail:
|
||||
if (0 != SvcJob)
|
||||
CloseHandle(SvcJob);
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != SvcInstanceTlsKey)
|
||||
TlsFree(SvcInstanceTlsKey);
|
||||
|
||||
if (0 != SvcInstanceEvent)
|
||||
CloseHandle(SvcInstanceEvent);
|
||||
|
||||
@ -1023,6 +1154,9 @@ static NTSTATUS SvcStop(FSP_SERVICE *Service)
|
||||
if (0 != SvcJob)
|
||||
CloseHandle(SvcJob);
|
||||
|
||||
if (TLS_OUT_OF_INDEXES != SvcInstanceTlsKey)
|
||||
TlsFree(SvcInstanceTlsKey);
|
||||
|
||||
if (0 != SvcInstanceEvent)
|
||||
CloseHandle(SvcInstanceEvent);
|
||||
|
||||
@ -1194,13 +1328,16 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
return;
|
||||
|
||||
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||
PWSTR ClassName, InstanceName;
|
||||
PWSTR ClassName, InstanceName, UserName;
|
||||
ULONG Argc; PWSTR Argv[9];
|
||||
BOOLEAN HasSecret = FALSE;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PSize = 0;
|
||||
|
||||
GetTokenUserName(ClientToken, &UserName);
|
||||
SvcInstanceSetUserName(UserName);
|
||||
|
||||
switch (*P++)
|
||||
{
|
||||
case LauncherSvcInstanceStartWithSecret:
|
||||
@ -1264,6 +1401,9 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||
SvcPipeTransactResult(STATUS_INVALID_PARAMETER, PipeBuf, PSize);
|
||||
break;
|
||||
}
|
||||
|
||||
SvcInstanceSetUserName(0);
|
||||
MemFree(UserName);
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **argv)
|
||||
|
@ -611,7 +611,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
|
||||
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
ASSERT(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) >=
|
||||
FileDesc->DirectoryMarker.Length);
|
||||
|
||||
Request->Req.QueryDirectory.Marker.Offset =
|
||||
@ -921,7 +921,7 @@ NTSTATUS FspFsvolDirectoryControlComplete(
|
||||
if (0 != FileDesc->DirectoryMarker.Buffer)
|
||||
{
|
||||
ASSERT(
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength >=
|
||||
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) >=
|
||||
FileDesc->DirectoryMarker.Length);
|
||||
|
||||
Request->Req.QueryDirectory.Marker.Offset =
|
||||
|
@ -2166,7 +2166,7 @@ NTSTATUS FspFileDescSetDirectoryMarker(FSP_FILE_DESC *FileDesc,
|
||||
FspFsvolDeviceExtension(FileDesc->FileNode->FsvolDeviceObject);
|
||||
UNICODE_STRING DirectoryMarker;
|
||||
|
||||
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength < FileName->Length)
|
||||
if (FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR) < FileName->Length)
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
DirectoryMarker.Length = DirectoryMarker.MaximumLength = FileName->Length;
|
||||
|
@ -657,7 +657,7 @@ exit /b 0
|
||||
|
||||
:sample-passthrough-dotnet
|
||||
call :__run_sample_test passthrough-dotnet anycpu passthrough-dotnet winfsp-tests-x64 ^
|
||||
"-create_backup_test -create_restore_test -create_namelen_test -delete_access_test"
|
||||
"-create_backup_test -create_restore_test -create_namelen_test -delete_access_test -querydir_namelen_test"
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
@ -725,7 +725,7 @@ L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%4.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -exec_rename_dir_test ^
|
||||
-getfileinfo_name_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
@ -784,8 +784,8 @@ cd L: >nul 2>nul || (echo Unable to find drive L: >&2 & goto fail)
|
||||
L:
|
||||
"%ProjRoot%\build\VStudio\build\%Configuration%\%3.exe" ^
|
||||
--external --resilient --case-insensitive-cmp --share-prefix="\%1\%TMP::=$%\%1\test" ^
|
||||
-create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -exec_rename_dir_test ^
|
||||
-create_fileattr_test -create_allocation_test -create_notraverse_test -create_backup_test -create_restore_test -create_namelen_test ^
|
||||
-getfileinfo_name_test -setfileinfo_test -delete_access_test -delete_mmap_test -rename_flipflop_test -rename_mmap_test -setsecurity_test -querydir_namelen_test -exec_rename_dir_test ^
|
||||
-reparse* -stream*
|
||||
if !ERRORLEVEL! neq 0 set RunSampleTestExit=1
|
||||
popd
|
||||
|
@ -375,6 +375,7 @@ namespace passthrough
|
||||
4096,
|
||||
0,
|
||||
Security));
|
||||
FileDesc.SetFileAttributes(FileAttributes | (UInt32)System.IO.FileAttributes.Archive);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -388,8 +389,8 @@ namespace passthrough
|
||||
}
|
||||
FileDesc = new FileDesc(
|
||||
Directory.CreateDirectory(FileName, Security));
|
||||
FileDesc.SetFileAttributes(FileAttributes);
|
||||
}
|
||||
FileDesc.SetFileAttributes(FileAttributes);
|
||||
FileNode = default(Object);
|
||||
FileDesc0 = FileDesc;
|
||||
NormalizedName = default(String);
|
||||
@ -453,9 +454,11 @@ namespace passthrough
|
||||
{
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (ReplaceFileAttributes)
|
||||
FileDesc.SetFileAttributes(FileAttributes);
|
||||
FileDesc.SetFileAttributes(FileAttributes |
|
||||
(UInt32)System.IO.FileAttributes.Archive);
|
||||
else if (0 != FileAttributes)
|
||||
FileDesc.SetFileAttributes(FileDesc.GetFileAttributes() | FileAttributes);
|
||||
FileDesc.SetFileAttributes(FileDesc.GetFileAttributes() | FileAttributes |
|
||||
(UInt32)System.IO.FileAttributes.Archive);
|
||||
FileDesc.Stream.SetLength(0);
|
||||
return FileDesc.GetFileInfo(out FileInfo);
|
||||
}
|
||||
@ -637,11 +640,17 @@ namespace passthrough
|
||||
FileDesc FileDesc = (FileDesc)FileDesc0;
|
||||
if (null == FileDesc.FileSystemInfos)
|
||||
{
|
||||
IEnumerable Enum = FileDesc.DirInfo.EnumerateFileSystemInfos(
|
||||
null != Pattern ? Pattern : "*");
|
||||
if (null != Pattern)
|
||||
Pattern = Pattern.Replace('<', '*').Replace('>', '?').Replace('"', '.');
|
||||
else
|
||||
Pattern = "*";
|
||||
IEnumerable Enum = FileDesc.DirInfo.EnumerateFileSystemInfos(Pattern);
|
||||
SortedList List = new SortedList();
|
||||
List.Add(".", FileDesc.DirInfo);
|
||||
List.Add("..", FileDesc.DirInfo.Parent);
|
||||
if (null != FileDesc.DirInfo && null != FileDesc.DirInfo.Parent)
|
||||
{
|
||||
List.Add(".", FileDesc.DirInfo);
|
||||
List.Add("..", FileDesc.DirInfo.Parent);
|
||||
}
|
||||
foreach (FileSystemInfo Info in Enum)
|
||||
List.Add(Info.Name, Info);
|
||||
FileDesc.FileSystemInfos = new DictionaryEntry[List.Count];
|
||||
|
@ -39,6 +39,11 @@ void create_dotest(ULONG Flags, PWSTR Prefix)
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||
ASSERT(ERROR_FILE_EXISTS == GetLastError());
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
@ -227,6 +232,122 @@ void create_test(void)
|
||||
create_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||
}
|
||||
|
||||
static void create_fileattr_dotest(ULONG Flags, PWSTR Prefix)
|
||||
{
|
||||
void *memfs = memfs_start(Flags);
|
||||
|
||||
HANDLE Handle;
|
||||
BOOLEAN Success;
|
||||
DWORD FileAttributes;
|
||||
WCHAR FilePath[MAX_PATH];
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT(FILE_ATTRIBUTE_ARCHIVE == FileAttributes);
|
||||
Success = DeleteFileW(FilePath);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_READONLY, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
Success = DeleteFileW(FilePath);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
Success = DeleteFileW(FilePath);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_HIDDEN, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
Success = DeleteFileW(FilePath);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT(FILE_ATTRIBUTE_ARCHIVE == FileAttributes);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_READONLY, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_SYSTEM) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
CloseHandle(Handle);
|
||||
|
||||
FileAttributes = GetFileAttributesW(FilePath);
|
||||
ASSERT((FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_HIDDEN) == FileAttributes);
|
||||
Success = SetFileAttributesW(FilePath, FILE_ATTRIBUTE_NORMAL);
|
||||
ASSERT(Success);
|
||||
|
||||
Success = DeleteFileW(FilePath);
|
||||
ASSERT(Success);
|
||||
|
||||
memfs_stop(memfs);
|
||||
}
|
||||
|
||||
static void create_fileattr_test(void)
|
||||
{
|
||||
if (NtfsTests)
|
||||
{
|
||||
WCHAR DirBuf[MAX_PATH];
|
||||
GetTestDirectory(DirBuf);
|
||||
create_fileattr_dotest(-1, DirBuf);
|
||||
}
|
||||
if (WinFspDiskTests)
|
||||
create_fileattr_dotest(MemfsDisk, 0);
|
||||
if (WinFspNetTests)
|
||||
create_fileattr_dotest(MemfsNet, L"\\\\memfs\\share");
|
||||
}
|
||||
|
||||
void create_related_dotest(ULONG Flags, PWSTR Prefix)
|
||||
{
|
||||
void *memfs = memfs_start(Flags);
|
||||
@ -1136,6 +1257,7 @@ void create_pid_test(void)
|
||||
void create_tests(void)
|
||||
{
|
||||
TEST(create_test);
|
||||
TEST(create_fileattr_test);
|
||||
TEST(create_related_test);
|
||||
TEST(create_allocation_test);
|
||||
TEST(create_sd_test);
|
||||
|
@ -416,6 +416,98 @@ void querydir_buffer_overflow_test(void)
|
||||
}
|
||||
}
|
||||
|
||||
static VOID querydir_namelen_exists(PWSTR FilePath)
|
||||
{
|
||||
HANDLE Handle;
|
||||
WIN32_FIND_DATAW FindData;
|
||||
|
||||
Handle = FindFirstFileW(FilePath, &FindData);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
FindClose(Handle);
|
||||
}
|
||||
|
||||
static void querydir_namelen_dotest(ULONG Flags, PWSTR Prefix, PWSTR Drive)
|
||||
{
|
||||
/* based on create_namelen_dotest */
|
||||
|
||||
void *memfs = memfs_start(Flags);
|
||||
|
||||
WCHAR FilePath[1024];
|
||||
PWSTR FilePathBgn, P, EndP;
|
||||
DWORD MaxComponentLength;
|
||||
HANDLE Handle;
|
||||
BOOL Success;
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Drive ? Drive : memfs_volumename(memfs));
|
||||
|
||||
Success = GetVolumeInformationW(FilePath,
|
||||
0, 0,
|
||||
0, &MaxComponentLength, 0,
|
||||
0, 0);
|
||||
ASSERT(Success);
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||
FilePathBgn = FilePath + wcslen(FilePath);
|
||||
|
||||
for (P = FilePathBgn, EndP = P + MaxComponentLength - 1; EndP > P; P++)
|
||||
*P = (P - FilePathBgn) % 10 + '0';
|
||||
*P = L'\0';
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
querydir_namelen_exists(FilePath);
|
||||
Success = CloseHandle(Handle);
|
||||
ASSERT(Success);
|
||||
|
||||
for (P = FilePathBgn, EndP = P + MaxComponentLength; EndP > P; P++)
|
||||
*P = (P - FilePathBgn) % 10 + '0';
|
||||
*P = L'\0';
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
querydir_namelen_exists(FilePath);
|
||||
Success = CloseHandle(Handle);
|
||||
ASSERT(Success);
|
||||
|
||||
for (P = FilePathBgn, EndP = P + MaxComponentLength + 1; EndP > P; P++)
|
||||
*P = (P - FilePathBgn) % 10 + '0';
|
||||
*P = L'\0';
|
||||
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE == Handle);
|
||||
ASSERT(ERROR_INVALID_NAME == GetLastError());
|
||||
|
||||
memfs_stop(memfs);
|
||||
}
|
||||
|
||||
static void querydir_namelen_test(void)
|
||||
{
|
||||
if (OptShareName || OptMountPoint)
|
||||
return;
|
||||
|
||||
if (NtfsTests)
|
||||
{
|
||||
WCHAR DirBuf[MAX_PATH], DriveBuf[3];
|
||||
GetTestDirectoryAndDrive(DirBuf, DriveBuf);
|
||||
querydir_namelen_dotest(-1, DirBuf, DriveBuf);
|
||||
}
|
||||
if (WinFspDiskTests)
|
||||
querydir_namelen_dotest(MemfsDisk, 0, 0);
|
||||
#if 0
|
||||
/* This test does not work when going through the MUP! */
|
||||
if (WinFspNetTests)
|
||||
querydir_namelen_dotest(MemfsNet, L"\\\\memfs\\share", L"\\\\memfs\\share");
|
||||
#endif
|
||||
}
|
||||
|
||||
static unsigned __stdcall dirnotify_dotest_thread(void *FilePath)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
||||
@ -552,5 +644,7 @@ void dirctl_tests(void)
|
||||
TEST(querydir_expire_cache_test);
|
||||
if (!OptShareName)
|
||||
TEST(querydir_buffer_overflow_test);
|
||||
if (!OptShareName && !OptMountPoint)
|
||||
TEST(querydir_namelen_test);
|
||||
TEST(dirnotify_test);
|
||||
}
|
||||
|
Reference in New Issue
Block a user