mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
dll: reparse point implementation: WIP
This commit is contained in:
parent
499a0cb866
commit
7ffc60f512
@ -137,6 +137,10 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* @param PFileAttributes
|
* @param PFileAttributes
|
||||||
* Pointer to a memory location that will receive the file attributes on successful return
|
* Pointer to a memory location that will receive the file attributes on successful return
|
||||||
* from this call. May be NULL.
|
* from this call. May be NULL.
|
||||||
|
*
|
||||||
|
* If this call returns STATUS_REPARSE, the file system MAY place here the index of the
|
||||||
|
* first reparse point within FileName. The file system MAY also leave this at its default
|
||||||
|
* value of 0.
|
||||||
* @param SecurityDescriptor
|
* @param SecurityDescriptor
|
||||||
* Pointer to a buffer that will receive the file security descriptor on successful return
|
* Pointer to a buffer that will receive the file security descriptor on successful return
|
||||||
* from this call. May be NULL.
|
* from this call. May be NULL.
|
||||||
@ -152,7 +156,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* component.
|
* component.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*GetSecurityByName)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*GetSecurityByName)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, PUINT32 PFileAttributes,
|
PWSTR FileName, PUINT32 PFileAttributes/* or ReparsePointIndex */,
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize);
|
PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize);
|
||||||
/**
|
/**
|
||||||
* Create new file or directory.
|
* Create new file or directory.
|
||||||
@ -634,6 +638,8 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* The file system on which this request is posted.
|
* The file system on which this request is posted.
|
||||||
* @param FileName
|
* @param FileName
|
||||||
* The name of the file or directory to have its reparse points resolved.
|
* The name of the file or directory to have its reparse points resolved.
|
||||||
|
* @param ReparsePointIndex
|
||||||
|
* The index of the first reparse point within FileName.
|
||||||
* @param OpenReparsePoint
|
* @param OpenReparsePoint
|
||||||
* If TRUE, the last path component of FileName should not be resolved, even
|
* If TRUE, the last path component of FileName should not be resolved, even
|
||||||
* if it is a reparse point that can be resolved. If FALSE, all path components
|
* if it is a reparse point that can be resolved. If FALSE, all path components
|
||||||
@ -653,7 +659,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
* STATUS_REPARSE or error code.
|
* STATUS_REPARSE or error code.
|
||||||
*/
|
*/
|
||||||
NTSTATUS (*ResolveReparsePoints)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*ResolveReparsePoints)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, BOOLEAN OpenReparsePoint,
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN OpenReparsePoint,
|
||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize);
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize);
|
||||||
/**
|
/**
|
||||||
* Get reparse point.
|
* Get reparse point.
|
||||||
@ -993,6 +999,91 @@ FSP_API NTSTATUS FspFileSystemOpSetSecurity(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*/
|
*/
|
||||||
FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
||||||
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
PVOID Buffer, ULONG Length, PULONG PBytesTransferred);
|
||||||
|
/**
|
||||||
|
* Find reparse point in file name.
|
||||||
|
*
|
||||||
|
* Given a file name this function returns an index to the first path component that is a reparse
|
||||||
|
* point. The function will call the supplied GetReparsePointByName function for every path
|
||||||
|
* component until it finds a reparse point or the whole path is processed.
|
||||||
|
*
|
||||||
|
* This is a helper for implementing the GetSecurityByName operation in file systems
|
||||||
|
* that support reparse points.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @param GetReparsePointByName
|
||||||
|
* Pointer to function that can retrieve reparse point information by name. The
|
||||||
|
* FspFileSystemFindReparsePoint will call this function with the Buffer and PSize
|
||||||
|
* arguments set to NULL. The function should return STATUS_SUCCESS if the passed
|
||||||
|
* FileName is a reparse point or STATUS_NOT_A_REPARSE_POINT (or other error code)
|
||||||
|
* otherwise.
|
||||||
|
* @param Context
|
||||||
|
* User context to supply to GetReparsePointByName.
|
||||||
|
* @param FileName
|
||||||
|
* The name of the file or directory.
|
||||||
|
* @param PReparsePointIndex
|
||||||
|
* Pointer to a memory location that will receive the index of the first reparse point
|
||||||
|
* within FileName. A value is only placed in this memory location if the function returns
|
||||||
|
* TRUE. May be NULL.
|
||||||
|
* @return
|
||||||
|
* TRUE if a reparse point was found, FALSE otherwise.
|
||||||
|
* @see
|
||||||
|
* GetSecurityByName
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context, PWSTR FileName, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
PVOID Context,
|
||||||
|
PWSTR FileName, PUINT32 PReparsePointIndex);
|
||||||
|
/**
|
||||||
|
* Resolve reparse points.
|
||||||
|
*
|
||||||
|
* Given a file name (and an index where to start resolving) this function will attempt to
|
||||||
|
* resolve as many reparse points as possible. The function will call the supplied
|
||||||
|
* GetReparsePointByName function for every path component until it resolves the reparse points
|
||||||
|
* or the whole path is processed.
|
||||||
|
*
|
||||||
|
* This is a helper for implementing the ResolveReparsePoints operation in file systems
|
||||||
|
* that support reparse points.
|
||||||
|
*
|
||||||
|
* @param FileSystem
|
||||||
|
* The file system object.
|
||||||
|
* @param GetReparsePointByName
|
||||||
|
* Pointer to function that can retrieve reparse point information by name. The function
|
||||||
|
* should return STATUS_SUCCESS if the passed FileName is a reparse point or
|
||||||
|
* STATUS_NOT_A_REPARSE_POINT (or other error code) otherwise.
|
||||||
|
* @param Context
|
||||||
|
* User context to supply to GetReparsePointByName.
|
||||||
|
* @param FileName
|
||||||
|
* The name of the file or directory to have its reparse points resolved.
|
||||||
|
* @param ReparsePointIndex
|
||||||
|
* The index of the first reparse point within FileName.
|
||||||
|
* @param OpenReparsePoint
|
||||||
|
* If TRUE, the last path component of FileName should not be resolved, even
|
||||||
|
* if it is a reparse point that can be resolved. If FALSE, all path components
|
||||||
|
* should be resolved if possible.
|
||||||
|
* @param PIoStatus
|
||||||
|
* Pointer to storage that will receive the status to return to the FSD. When
|
||||||
|
* this function succeeds it must set PIoStatus->Status to STATUS_REPARSE and
|
||||||
|
* PIoStatus->Information to either IO_REPARSE or the reparse tag.
|
||||||
|
* @param Buffer
|
||||||
|
* Pointer to a buffer that will receive the resolved file name (IO_REPARSE) or
|
||||||
|
* reparse data (reparse tag). If the function returns a file name, it should
|
||||||
|
* not be NULL terminated.
|
||||||
|
* @param PSize [in,out]
|
||||||
|
* Pointer to the buffer size. On input it contains the size of the buffer.
|
||||||
|
* On output it will contain the actual size of data copied.
|
||||||
|
* @return
|
||||||
|
* STATUS_REPARSE or error code.
|
||||||
|
* @see
|
||||||
|
* ResolveReparsePoints
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context, PWSTR FileName, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
PVOID Context,
|
||||||
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN OpenReparsePoint,
|
||||||
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Security
|
* Security
|
||||||
@ -1001,7 +1092,7 @@ FSP_API PGENERIC_MAPPING FspGetFileGenericMapping(VOID);
|
|||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
||||||
UINT32 DesiredAccess, PUINT32 PGrantedAccess,
|
UINT32 DesiredAccess, PUINT32 PGrantedAccess/* or ReparsePointIndex */,
|
||||||
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
PSECURITY_DESCRIPTOR *PSecurityDescriptor);
|
||||||
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspCreateSecurityDescriptor(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
|
292
src/dll/fsop.c
292
src/dll/fsop.c
@ -121,8 +121,9 @@ FSP_API NTSTATUS FspFileSystemOpLeave(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS FspFileSystemCallResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response,
|
||||||
|
UINT32 ReparsePointIndex)
|
||||||
{
|
{
|
||||||
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
@ -134,12 +135,27 @@ NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer);
|
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer);
|
||||||
Result = FileSystem->Interface->ResolveReparsePoints(FileSystem,
|
Result = FileSystem->Interface->ResolveReparsePoints(FileSystem,
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
|
ReparsePointIndex,
|
||||||
!!(Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT),
|
!!(Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT),
|
||||||
&IoStatus,
|
&IoStatus,
|
||||||
Response->Buffer,
|
Response->Buffer,
|
||||||
&Size);
|
&Size);
|
||||||
if (STATUS_REPARSE == Result)
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = STATUS_REPARSE;
|
||||||
Response->IoStatus.Information = (UINT32)IoStatus.Information;
|
Response->IoStatus.Information = (UINT32)IoStatus.Information;
|
||||||
|
|
||||||
|
if (0/*IO_REPARSE*/ == IoStatus.Information)
|
||||||
|
{
|
||||||
|
Response->Rsp.Create.Reparse.FileName.Offset = 0;
|
||||||
|
Response->Rsp.Create.Reparse.FileName.Size = (UINT16)Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Response->Rsp.Create.Reparse.Data.Offset = 0;
|
||||||
|
Response->Rsp.Create.Reparse.Data.Size = (UINT16)Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
@ -167,7 +183,10 @@ NTSTATUS FspFileSystemCreateCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
FILE_ADD_SUBDIRECTORY : FILE_ADD_FILE,
|
||||||
PGrantedAccess, PSecurityDescriptor);
|
PGrantedAccess, PSecurityDescriptor);
|
||||||
if (STATUS_REPARSE == Result)
|
if (STATUS_REPARSE == Result)
|
||||||
Result = FspFileSystemResolveReparsePoints(FileSystem, Request, Response);
|
{
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
|
||||||
|
*PGrantedAccess = 0;
|
||||||
|
}
|
||||||
else if (NT_SUCCESS(Result))
|
else if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
*PGrantedAccess = (MAXIMUM_ALLOWED & Request->Req.Create.DesiredAccess) ?
|
||||||
@ -199,7 +218,10 @@ NTSTATUS FspFileSystemOpenCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
|
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
|
||||||
PGrantedAccess);
|
PGrantedAccess);
|
||||||
if (STATUS_REPARSE == Result)
|
if (STATUS_REPARSE == Result)
|
||||||
Result = FspFileSystemResolveReparsePoints(FileSystem, Request, Response);
|
{
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
|
||||||
|
*PGrantedAccess = 0;
|
||||||
|
}
|
||||||
else if (NT_SUCCESS(Result))
|
else if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
||||||
@ -234,7 +256,10 @@ NTSTATUS FspFileSystemOverwriteCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
|
((Request->Req.Create.CreateOptions & FILE_DELETE_ON_CLOSE) ? DELETE : 0),
|
||||||
PGrantedAccess);
|
PGrantedAccess);
|
||||||
if (STATUS_REPARSE == Result)
|
if (STATUS_REPARSE == Result)
|
||||||
Result = FspFileSystemResolveReparsePoints(FileSystem, Request, Response);
|
{
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
|
||||||
|
*PGrantedAccess = 0;
|
||||||
|
}
|
||||||
else if (NT_SUCCESS(Result))
|
else if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
if (0 == (Request->Req.Create.DesiredAccess & MAXIMUM_ALLOWED))
|
||||||
@ -260,7 +285,10 @@ NTSTATUS FspFileSystemOpenTargetDirectoryCheck(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Request->Req.Create.DesiredAccess,
|
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE, Request->Req.Create.DesiredAccess,
|
||||||
PGrantedAccess);
|
PGrantedAccess);
|
||||||
if (STATUS_REPARSE == Result)
|
if (STATUS_REPARSE == Result)
|
||||||
Result = FspFileSystemResolveReparsePoints(FileSystem, Request, Response);
|
{
|
||||||
|
Result = FspFileSystemCallResolveReparsePoints(FileSystem, Request, Response, *PGrantedAccess);
|
||||||
|
*PGrantedAccess = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -894,7 +922,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
PREPARSE_DATA_BUFFER SymlinkReparseData;
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
SIZE_T Offset, Size;
|
SIZE_T Offset, Size;
|
||||||
|
|
||||||
Result = STATUS_INVALID_DEVICE_REQUEST;
|
Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
@ -903,42 +931,39 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
case FSCTL_GET_REPARSE_POINT:
|
case FSCTL_GET_REPARSE_POINT:
|
||||||
if (0 != FileSystem->Interface->GetReparsePoint)
|
if (0 != FileSystem->Interface->GetReparsePoint)
|
||||||
{
|
{
|
||||||
SymlinkReparseData = (PREPARSE_DATA_BUFFER)Response->Buffer;
|
ReparseData = (PREPARSE_DATA_BUFFER)Response->Buffer;
|
||||||
memset(SymlinkReparseData, 0, sizeof *SymlinkReparseData);
|
memset(ReparseData, 0,
|
||||||
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer));
|
||||||
|
|
||||||
if (FileSystem->ReparsePointsSymbolicLinks)
|
if (FileSystem->ReparsePointsSymbolicLinks)
|
||||||
{
|
{
|
||||||
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer) -
|
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer) -
|
||||||
sizeof(*SymlinkReparseData);
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer);
|
||||||
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)Request->Req.FileSystemControl.UserContext,
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer,
|
ReparseData->SymbolicLinkReparseBuffer.PathBuffer,
|
||||||
&Size);
|
&Size);
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
Offset = 0;
|
Offset = 0;
|
||||||
if (Size > 4 * sizeof(WCHAR) &&
|
if (Size > 4 * sizeof(WCHAR) &&
|
||||||
'\\' == SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer[0] &&
|
'\\' == ReparseData->SymbolicLinkReparseBuffer.PathBuffer[0] &&
|
||||||
'?' == SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer[1] &&
|
'?' == ReparseData->SymbolicLinkReparseBuffer.PathBuffer[1] &&
|
||||||
'?' == SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer[2] &&
|
'?' == ReparseData->SymbolicLinkReparseBuffer.PathBuffer[2] &&
|
||||||
'\\' == SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer[3])
|
'\\' == ReparseData->SymbolicLinkReparseBuffer.PathBuffer[3])
|
||||||
Offset = 4 * sizeof(WCHAR);
|
Offset = 4 * sizeof(WCHAR);
|
||||||
|
|
||||||
SymlinkReparseData->ReparseTag = IO_REPARSE_TAG_SYMLINK;
|
ReparseData->ReparseTag = IO_REPARSE_TAG_SYMLINK;
|
||||||
SymlinkReparseData->ReparseDataLength = (USHORT)(
|
ReparseData->ReparseDataLength = (USHORT)(
|
||||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) -
|
||||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer) +
|
FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer) +
|
||||||
Size);
|
Size);
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset =
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0;
|
||||||
0;
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength = (USHORT)Size;
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength =
|
ReparseData->SymbolicLinkReparseBuffer.PrintNameOffset = (USHORT)Offset;
|
||||||
(USHORT)Size;
|
ReparseData->SymbolicLinkReparseBuffer.PrintNameLength = (USHORT)(Size - Offset);
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.PrintNameOffset =
|
ReparseData->SymbolicLinkReparseBuffer.Flags = 0 == Offset ?
|
||||||
(USHORT)Offset;
|
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.PrintNameLength =
|
|
||||||
(USHORT)(Size - Offset);
|
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.Flags = 0 == Offset ?
|
|
||||||
0 : SYMLINK_FLAG_RELATIVE;
|
0 : SYMLINK_FLAG_RELATIVE;
|
||||||
|
|
||||||
Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)Size;
|
Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)Size;
|
||||||
@ -949,7 +974,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer);
|
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer);
|
||||||
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)Request->Req.FileSystemControl.UserContext,
|
||||||
(PWSTR)Request->Buffer, SymlinkReparseData, &Size);
|
(PWSTR)Request->Buffer, ReparseData, &Size);
|
||||||
if (NT_SUCCESS(Result))
|
if (NT_SUCCESS(Result))
|
||||||
Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)Size;
|
Response->Rsp.FileSystemControl.Buffer.Size = (UINT16)Size;
|
||||||
}
|
}
|
||||||
@ -958,7 +983,7 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
case FSCTL_SET_REPARSE_POINT:
|
case FSCTL_SET_REPARSE_POINT:
|
||||||
if (0 != FileSystem->Interface->SetReparsePoint)
|
if (0 != FileSystem->Interface->SetReparsePoint)
|
||||||
{
|
{
|
||||||
SymlinkReparseData = (PREPARSE_DATA_BUFFER)
|
ReparseData = (PREPARSE_DATA_BUFFER)
|
||||||
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
|
||||||
|
|
||||||
if (FileSystem->ReparsePointsSymbolicLinks)
|
if (FileSystem->ReparsePointsSymbolicLinks)
|
||||||
@ -966,15 +991,15 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)Request->Req.FileSystemControl.UserContext,
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||||
SymlinkReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength);
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
|
||||||
(PVOID)Request->Req.FileSystemControl.UserContext,
|
(PVOID)Request->Req.FileSystemControl.UserContext,
|
||||||
(PWSTR)Request->Buffer,
|
(PWSTR)Request->Buffer,
|
||||||
SymlinkReparseData,
|
ReparseData,
|
||||||
Request->Req.FileSystemControl.Buffer.Size);
|
Request->Req.FileSystemControl.Buffer.Size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1053,3 +1078,204 @@ FSP_API BOOLEAN FspFileSystemAddDirInfo(FSP_FSCTL_DIR_INFO *DirInfo,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspFileSystemFindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context, PWSTR FileName, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
PVOID Context,
|
||||||
|
PWSTR FileName, PUINT32 PReparsePointIndex)
|
||||||
|
{
|
||||||
|
PWSTR p, lastp;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
p = FileName;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (L'\\' == *p)
|
||||||
|
p++;
|
||||||
|
lastp = p;
|
||||||
|
while (L'\\' != *p)
|
||||||
|
{
|
||||||
|
if (L'\0' == *p)
|
||||||
|
return FALSE;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p = L'\0';
|
||||||
|
Result = GetReparsePointByName(FileSystem, Context, FileName, 0, 0);
|
||||||
|
*p = L'\\';
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 != PReparsePointIndex)
|
||||||
|
*PReparsePointIndex = (ULONG)(lastp - FileName);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
|
NTSTATUS (*GetReparsePointByName)(
|
||||||
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context, PWSTR FileName, PVOID Buffer, PSIZE_T PSize),
|
||||||
|
PVOID Context,
|
||||||
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN OpenReparsePoint,
|
||||||
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
|
{
|
||||||
|
WCHAR c, *p, *lastp;
|
||||||
|
PWSTR TargetPath, TargetPathEnd, TargetLink;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
REPARSE_DATA_BUFFER V;
|
||||||
|
UINT8 B[FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) +
|
||||||
|
/* assumption: the substitute and print paths are stored in the same buffer */
|
||||||
|
FSP_FSCTL_TRANSACT_PATH_SIZEMAX];
|
||||||
|
} ReparseDataBuf;
|
||||||
|
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
|
||||||
|
SIZE_T Size, MaxTries = 32;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
TargetPath = Buffer;
|
||||||
|
TargetPathEnd = TargetPath + *PSize / sizeof(WCHAR);
|
||||||
|
Size = (lstrlenW(FileName) + 1) * sizeof(WCHAR);
|
||||||
|
if (Size > *PSize)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
memcpy(TargetPath, FileName, Size);
|
||||||
|
|
||||||
|
p = TargetPath + ReparsePointIndex;
|
||||||
|
c = *p;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (L'\\' == *p)
|
||||||
|
p++;
|
||||||
|
lastp = p;
|
||||||
|
while (L'\\' != *p)
|
||||||
|
{
|
||||||
|
if (L'\0' == *p)
|
||||||
|
{
|
||||||
|
if (!OpenReparsePoint)
|
||||||
|
goto exit;
|
||||||
|
OpenReparsePoint = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle dot and dotdot! */
|
||||||
|
if (L'.' == lastp[0])
|
||||||
|
{
|
||||||
|
if (p == lastp + 1)
|
||||||
|
/* dot */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (L'.' == lastp[1] && p == lastp + 1)
|
||||||
|
{
|
||||||
|
/* dotdot */
|
||||||
|
p = lastp;
|
||||||
|
while (TargetPath < p)
|
||||||
|
{
|
||||||
|
p--;
|
||||||
|
if (L'\\' != *p)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while (TargetPath < p)
|
||||||
|
{
|
||||||
|
p--;
|
||||||
|
if (L'\\' == *p)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c = *p;
|
||||||
|
*p = '\0';
|
||||||
|
if (FileSystem->ReparsePointsSymbolicLinks)
|
||||||
|
{
|
||||||
|
Size = FSP_FSCTL_TRANSACT_PATH_SIZEMAX;
|
||||||
|
Result = GetReparsePointByName(FileSystem, Context, TargetPath,
|
||||||
|
ReparseData->SymbolicLinkReparseBuffer.PathBuffer, &Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Size = sizeof ReparseDataBuf;
|
||||||
|
Result = GetReparsePointByName(FileSystem, Context, TargetPath,
|
||||||
|
ReparseData, &Size);
|
||||||
|
}
|
||||||
|
*p = c;
|
||||||
|
|
||||||
|
if (STATUS_NOT_A_REPARSE_POINT == Result)
|
||||||
|
/* it was not a reparse point; continue */
|
||||||
|
continue;
|
||||||
|
else if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
/* found a reparse point */
|
||||||
|
|
||||||
|
if (0 == --MaxTries)
|
||||||
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
|
if (FileSystem->ReparsePointsSymbolicLinks)
|
||||||
|
TargetLink = ReparseData->SymbolicLinkReparseBuffer.PathBuffer;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IO_REPARSE_TAG_SYMLINK == ReparseData->ReparseTag)
|
||||||
|
{
|
||||||
|
TargetLink = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset;
|
||||||
|
Size = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* not a symlink; return the full reparse point! */
|
||||||
|
if (Size > *PSize)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
memcpy(Buffer, ReparseData, Size);
|
||||||
|
|
||||||
|
goto no_symlink_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Size > 4 * sizeof(WCHAR) &&
|
||||||
|
'\\' == TargetLink[0] &&
|
||||||
|
'?' == TargetLink[1] &&
|
||||||
|
'?' == TargetLink[2] &&
|
||||||
|
'\\' == TargetLink[3])
|
||||||
|
{
|
||||||
|
/* absolute symlink; replace whole path */
|
||||||
|
if (Size > *PSize)
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
memcpy(TargetPath, TargetLink, Size);
|
||||||
|
p = TargetPath + Size / sizeof(WCHAR);
|
||||||
|
|
||||||
|
/* absolute symlinks on Windows are in NT namespace; send to FSD for further processing */
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* relative symlink; replace last path component seen */
|
||||||
|
if (Size + sizeof(WCHAR) > (TargetPathEnd - lastp) * sizeof(WCHAR))
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
memcpy(lastp, TargetLink, Size);
|
||||||
|
lastp[Size / sizeof(WCHAR)] = L'\0';
|
||||||
|
p = lastp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
*PSize = (PUINT8)p - (PUINT8)TargetPath;
|
||||||
|
PIoStatus->Status = STATUS_REPARSE;
|
||||||
|
PIoStatus->Information = 0/*IO_REPARSE*/;
|
||||||
|
return STATUS_REPARSE;
|
||||||
|
|
||||||
|
no_symlink_exit:
|
||||||
|
*PSize = Size;
|
||||||
|
PIoStatus->Status = STATUS_REPARSE;
|
||||||
|
PIoStatus->Information = ReparseData->ReparseTag;
|
||||||
|
return STATUS_REPARSE;
|
||||||
|
}
|
||||||
|
@ -17,14 +17,6 @@
|
|||||||
|
|
||||||
#include <dll/fuse/library.h>
|
#include <dll/fuse/library.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* FSP_FUSE_REPARSE_OPTHACK
|
|
||||||
*
|
|
||||||
* Define this macro to enable the ResolveReparsePoints optimization hack.
|
|
||||||
* See fsp_fuse_intf_GetSecurityByName for details.
|
|
||||||
*/
|
|
||||||
#define FSP_FUSE_REPARSE_OPTHACK
|
|
||||||
|
|
||||||
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS fsp_fuse_op_enter(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FSCTL_TRANSACT_RSP *Response)
|
||||||
{
|
{
|
||||||
@ -314,8 +306,8 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *fsp_fuse_intf_GetSymlinkPointer(FSP_FILE_SYSTEM *FileSystem,
|
static BOOLEAN fsp_fuse_intf_FindReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
||||||
char *PosixPath)
|
char *PosixPath, PUINT32 PReparsePointIndex)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
char *p, *lastp;
|
char *p, *lastp;
|
||||||
@ -323,7 +315,7 @@ static char *fsp_fuse_intf_GetSymlinkPointer(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (0 == f->ops.getattr)
|
if (0 == f->ops.getattr)
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
p = PosixPath;
|
p = PosixPath;
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -334,7 +326,7 @@ static char *fsp_fuse_intf_GetSymlinkPointer(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
while ('/' != *p)
|
while ('/' != *p)
|
||||||
{
|
{
|
||||||
if ('\0' == *p)
|
if ('\0' == *p)
|
||||||
return 0;
|
return FALSE;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,12 +336,17 @@ static char *fsp_fuse_intf_GetSymlinkPointer(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*p = '/';
|
*p = '/';
|
||||||
|
|
||||||
if (0 != err)
|
if (0 != err)
|
||||||
return 0;
|
return FALSE;
|
||||||
else if (0120000 == (stbuf.st_mode & 0170000))
|
else if (0120000 == (stbuf.st_mode & 0170000))
|
||||||
return lastp;
|
{
|
||||||
|
if (0 != PReparsePointIndex)
|
||||||
|
*PReparsePointIndex = (ULONG)(lastp - PosixPath);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_GetVolumeInfo(FSP_FILE_SYSTEM *FileSystem,
|
||||||
@ -393,7 +390,7 @@ static NTSTATUS fsp_fuse_intf_GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize)
|
PSECURITY_DESCRIPTOR SecurityDescriptorBuf, SIZE_T *PSecurityDescriptorSize)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
char *PosixPath = 0, *PosixSymlinkPointer;
|
char *PosixPath = 0;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = FspPosixMapWindowsToPosixPath(FileName, &PosixPath);
|
Result = FspPosixMapWindowsToPosixPath(FileName, &PosixPath);
|
||||||
@ -406,28 +403,8 @@ static NTSTATUS fsp_fuse_intf_GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (FSP_FUSE_HAS_SYMLINKS(f) &&
|
if (FSP_FUSE_HAS_SYMLINKS(f) &&
|
||||||
0 != (PosixSymlinkPointer = fsp_fuse_intf_GetSymlinkPointer(FileSystem, PosixPath)))
|
fsp_fuse_intf_FindReparsePoint(FileSystem, PosixPath, PFileAttributes))
|
||||||
{
|
|
||||||
#if defined(FSP_FUSE_REPARSE_OPTHACK)
|
|
||||||
/* OPTHACK: This is a rather gross hack for optimization purposes only.
|
|
||||||
*
|
|
||||||
* If the FileName in this GetSecurityByName call and the PosixPath we computed
|
|
||||||
* matches the one in the FSD request, then remember where the first symlink is
|
|
||||||
* for use in ResolveReparsePoints later on. This avoids going through every path
|
|
||||||
* component twice (doing both a getattr and readlink).
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct fuse_context *context = fsp_fuse_get_context(f->env);
|
|
||||||
struct fsp_fuse_context_header *contexthdr = FSP_FUSE_HDR_FROM_CONTEXT(context);
|
|
||||||
|
|
||||||
if (FspFsctlTransactCreateKind == contexthdr->Request->Kind &&
|
|
||||||
(PUINT8)FileName == contexthdr->Request->Buffer &&
|
|
||||||
0 == lstrcmpA(PosixPath, contexthdr->PosixPath))
|
|
||||||
contexthdr->SymlinkIndex = PosixSymlinkPointer - PosixPath;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Result = STATUS_REPARSE;
|
Result = STATUS_REPARSE;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
@ -1510,7 +1487,7 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
||||||
PWSTR FileName, BOOLEAN OpenReparsePoint,
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN OpenReparsePoint,
|
||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
{
|
{
|
||||||
struct fuse *f = FileSystem->UserContext;
|
struct fuse *f = FileSystem->UserContext;
|
||||||
@ -1532,8 +1509,7 @@ static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_OBJECT_NAME_INVALID;
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
memcpy(PosixTargetPath, contexthdr->PosixPath, Length + 1);
|
memcpy(PosixTargetPath, contexthdr->PosixPath, Length + 1);
|
||||||
|
|
||||||
p = PosixTargetPath +
|
p = PosixTargetPath + ReparsePointIndex;
|
||||||
contexthdr->SymlinkIndex; /* NOTE: if FSP_FUSE_REPARSE_OPTHACK is undefined, this will be 0 */
|
|
||||||
c = *p;
|
c = *p;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -1581,7 +1557,7 @@ static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
c = *p;
|
c = *p;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
err = f->ops.readlink(contexthdr->PosixPath, PosixTargetLink, sizeof PosixTargetLink);
|
err = f->ops.readlink(PosixTargetPath, PosixTargetLink, sizeof PosixTargetLink);
|
||||||
*p = c;
|
*p = c;
|
||||||
|
|
||||||
if (EINVAL/* same on MSVC and Cygwin */ == err)
|
if (EINVAL/* same on MSVC and Cygwin */ == err)
|
||||||
@ -1598,10 +1574,7 @@ static NTSTATUS fsp_fuse_intf_ResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
{
|
{
|
||||||
/* we do not support absolute paths without the rellinks option */
|
/* we do not support absolute paths without the rellinks option */
|
||||||
if (!f->rellinks)
|
if (!f->rellinks)
|
||||||
{
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* absolute symlink; replace whole path */
|
/* absolute symlink; replace whole path */
|
||||||
memcpy(PosixTargetPath, PosixTargetLink, Length + 1);
|
memcpy(PosixTargetPath, PosixTargetLink, Length + 1);
|
||||||
|
@ -54,7 +54,6 @@ struct fsp_fuse_context_header
|
|||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
FSP_FSCTL_TRANSACT_RSP *Response;
|
||||||
char *PosixPath;
|
char *PosixPath;
|
||||||
ptrdiff_t SymlinkIndex;
|
|
||||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ContextBuf[];
|
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 ContextBuf[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,6 +48,19 @@ static NTSTATUS FspGetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline ULONG FspPathSuffixIndex(PWSTR FileName)
|
||||||
|
{
|
||||||
|
WCHAR Root[2] = L"\\";
|
||||||
|
PWSTR Remain, Suffix;
|
||||||
|
ULONG Result;
|
||||||
|
|
||||||
|
FspPathSuffix(FileName, &Remain, &Suffix, Root);
|
||||||
|
Result = Remain == Root ? 0 : (ULONG)(Suffix - Remain);
|
||||||
|
FspPathCombine(FileName, Suffix);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
BOOLEAN CheckParentDirectory, BOOLEAN AllowTraverseCheck,
|
||||||
@ -76,7 +89,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
WCHAR Root[2] = L"\\", TraverseCheckRoot[2] = L"\\";
|
WCHAR Root[2] = L"\\", TraverseCheckRoot[2] = L"\\";
|
||||||
PWSTR FileName, Suffix, Prefix, Remain;
|
PWSTR FileName, Suffix, Prefix, Remain;
|
||||||
UINT32 FileAttributes;
|
UINT32 FileAttributes = 0;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
SIZE_T SecurityDescriptorSize;
|
SIZE_T SecurityDescriptorSize;
|
||||||
UINT8 PrivilegeSetBuf[sizeof(PRIVILEGE_SET) + 15 * sizeof(LUID_AND_ATTRIBUTES)];
|
UINT8 PrivilegeSetBuf[sizeof(PRIVILEGE_SET) + 15 * sizeof(LUID_AND_ATTRIBUTES)];
|
||||||
@ -111,9 +124,15 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileAttributes = 0;
|
||||||
Result = FspGetSecurityByName(FileSystem, Prefix, &FileAttributes,
|
Result = FspGetSecurityByName(FileSystem, Prefix, &FileAttributes,
|
||||||
&SecurityDescriptor, &SecurityDescriptorSize);
|
&SecurityDescriptor, &SecurityDescriptorSize);
|
||||||
|
|
||||||
|
/* compute the ReparsePointIndex and place it in FileAttributes now */
|
||||||
|
if (NT_SUCCESS(Result) && STATUS_REPARSE != Result &&
|
||||||
|
(FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||||
|
FileAttributes = FspPathSuffixIndex(Prefix);
|
||||||
|
|
||||||
FspPathCombine(FileName, Remain);
|
FspPathCombine(FileName, Remain);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
|
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
|
||||||
@ -139,6 +158,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*/
|
*/
|
||||||
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
{
|
{
|
||||||
|
/* ReparsePointIndex already computed after FspGetSecurityByName call above */
|
||||||
Result = STATUS_REPARSE;
|
Result = STATUS_REPARSE;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -165,6 +185,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileAttributes = 0;
|
||||||
Result = FspGetSecurityByName(FileSystem, FileName, &FileAttributes,
|
Result = FspGetSecurityByName(FileSystem, FileName, &FileAttributes,
|
||||||
&SecurityDescriptor, &SecurityDescriptorSize);
|
&SecurityDescriptor, &SecurityDescriptorSize);
|
||||||
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
|
if (!NT_SUCCESS(Result) || STATUS_REPARSE == Result)
|
||||||
@ -237,6 +258,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
*/
|
*/
|
||||||
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
if (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
{
|
{
|
||||||
|
FileAttributes = FspPathSuffixIndex(FileName);
|
||||||
Result = STATUS_REPARSE;
|
Result = STATUS_REPARSE;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -256,6 +278,7 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
if (0 != (FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||||
0 == (Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT))
|
0 == (Request->Req.Create.CreateOptions & FILE_OPEN_REPARSE_POINT))
|
||||||
{
|
{
|
||||||
|
FileAttributes = FspPathSuffixIndex(FileName);
|
||||||
Result = STATUS_REPARSE;
|
Result = STATUS_REPARSE;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@ -307,7 +330,9 @@ FSP_API NTSTATUS FspAccessCheckEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
Result = STATUS_SUCCESS;
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (0 != PSecurityDescriptor && 0 < SecurityDescriptorSize && NT_SUCCESS(Result))
|
if (STATUS_REPARSE == Result)
|
||||||
|
*PGrantedAccess = FileAttributes; /* FileAttributes contains ReparsePointIndex */
|
||||||
|
else if (0 != PSecurityDescriptor && 0 < SecurityDescriptorSize && NT_SUCCESS(Result))
|
||||||
*PSecurityDescriptor = SecurityDescriptor;
|
*PSecurityDescriptor = SecurityDescriptor;
|
||||||
else
|
else
|
||||||
MemFree(SecurityDescriptor);
|
MemFree(SecurityDescriptor);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user