sys,dll: reparse point implementation: DeleteReparsePoint

This commit is contained in:
Bill Zissimopoulos 2016-08-26 07:43:25 -07:00
parent b88b2ec51d
commit 80e07cead6
6 changed files with 297 additions and 73 deletions

View File

@ -182,7 +182,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -207,7 +207,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -235,7 +235,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -263,7 +263,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;version.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -766,12 +766,41 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode,
PWSTR FileName, PVOID Buffer, SIZE_T Size);
/**
* Delete reparse point.
*
* The behavior of this function depends on the value of FSP_FSCTL_VOLUME_PARAMS ::
* ReparsePointsSymlinkOnly. If the value of ReparsePointsSymlinkOnly
* is FALSE the file system supports full reparse points and this function is expected
* to delete the reparse point contained in the buffer. If the value of
* ReparsePointsSymlinkOnly is TRUE the file system supports symbolic links only
* as reparse points and the Buffer and Size arguments will be NULL.
*
* @param FileSystem
* The file system on which this request is posted.
* @param Request
* The request posted by the kernel mode FSD.
* @param FileNode
* The file node of the reparse point.
* @param FileName
* The file name of the reparse point.
* @param Buffer
* Pointer to a buffer that contains the data for this operation.
* @param Size
* Size of data to write.
* @return
* STATUS_SUCCESS or error code.
*/
NTSTATUS (*DeleteReparsePoint)(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode,
PWSTR FileName, PVOID Buffer, SIZE_T Size);
/*
* This ensures that this interface will always contain 64 function pointers.
* Please update when changing the interface as it is important for future compatibility.
*/
NTSTATUS (*Reserved[42])();
NTSTATUS (*Reserved[41])();
} FSP_FILE_SYSTEM_INTERFACE;
#if defined(WINFSP_DLL_INTERNAL)
/*
@ -1126,6 +1155,29 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
PVOID Context,
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN OpenReparsePoint,
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize);
/**
* Test whether reparse data can be replaced.
*
* This is a helper for implementing the SetReparsePoint/DeleteReparsePoint operation
* in file systems that support reparse points.
*
* @param CurrentReparseData
* Pointer to the current reparse data.
* @param CurrentReparseDataSize
* Pointer to the current reparse data size.
* @param ReplaceReparseData
* Pointer to the replacement reparse data.
* @param ReplaceReparseDataSize
* Pointer to the replacement reparse data size.
* @return
* STATUS_SUCCESS or error code.
* @see
* SetReparsePoint
* DeleteReparsePoint
*/
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize);
/*
* Security

View File

@ -954,12 +954,15 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
if (FileSystem->ReparsePointsSymlinkOnly)
{
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
(PVOID)Request->Req.FileSystemControl.UserContext,
(PWSTR)Request->Buffer,
SetReparseData->SymbolicLinkReparseBuffer.PathBuffer +
SetReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
SetReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength);
if (IO_REPARSE_TAG_SYMLINK == *(PULONG)SetReparseData)
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
(PVOID)Request->Req.FileSystemControl.UserContext,
(PWSTR)Request->Buffer,
SetReparseData->SymbolicLinkReparseBuffer.PathBuffer +
SetReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
SetReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength);
else
Result = STATUS_IO_REPARSE_TAG_MISMATCH;
}
else
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
@ -970,58 +973,27 @@ FSP_API NTSTATUS FspFileSystemOpFileSystemControl(FSP_FILE_SYSTEM *FileSystem,
}
break;
case FSCTL_DELETE_REPARSE_POINT:
if (0 != FileSystem->Interface->GetReparsePoint &&
0 != FileSystem->Interface->SetReparsePoint)
if (0 != FileSystem->Interface->DeleteReparsePoint)
{
GetReparseData = (PREPARSE_DATA_BUFFER)Response->Buffer;
memset(GetReparseData, 0, sizeof *GetReparseData);
SetReparseData = (PREPARSE_DATA_BUFFER)
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
if (FileSystem->ReparsePointsSymlinkOnly)
{
GetReparseData->ReparseTag = IO_REPARSE_TAG_SYMLINK;
Result = STATUS_SUCCESS;
if (IO_REPARSE_TAG_SYMLINK == *(PULONG)SetReparseData)
Result = FileSystem->Interface->DeleteReparsePoint(FileSystem, Request,
(PVOID)Request->Req.FileSystemControl.UserContext,
(PWSTR)Request->Buffer,
0, 0);
else
Result = STATUS_IO_REPARSE_TAG_MISMATCH;
}
else
{
Size = FSP_FSCTL_TRANSACT_RSP_SIZEMAX - FIELD_OFFSET(FSP_FSCTL_TRANSACT_RSP, Buffer);
Result = FileSystem->Interface->GetReparsePoint(FileSystem, Request,
Result = FileSystem->Interface->DeleteReparsePoint(FileSystem, Request,
(PVOID)Request->Req.FileSystemControl.UserContext,
(PWSTR)Request->Buffer, GetReparseData, &Size);
}
if (NT_SUCCESS(Result))
{
SetReparseData = (PREPARSE_DATA_BUFFER)
(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset);
if (GetReparseData->ReparseTag != SetReparseData->ReparseTag)
Result = STATUS_IO_REPARSE_TAG_MISMATCH;
else if (!IsReparseTagMicrosoft(SetReparseData->ReparseTag) && (
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data1 !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data1 ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data2 !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data2 ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data3 !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data3 ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[0] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[0] ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[1] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[1] ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[2] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[2] ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[3] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[3] ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[4] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[4] ||
((PREPARSE_GUID_DATA_BUFFER)GetReparseData)->ReparseGuid.Data4[5] !=
((PREPARSE_GUID_DATA_BUFFER)SetReparseData)->ReparseGuid.Data4[5]))
Result = STATUS_REPARSE_ATTRIBUTE_CONFLICT;
if (NT_SUCCESS(Result))
Result = FileSystem->Interface->SetReparsePoint(FileSystem, Request,
(PVOID)Request->Req.FileSystemControl.UserContext,
(PWSTR)Request->Buffer, 0, 0);
}
(PWSTR)Request->Buffer,
SetReparseData,
Request->Req.FileSystemControl.Buffer.Size);
}
break;
}
@ -1231,8 +1203,7 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
continue;
else if (!NT_SUCCESS(Result))
{
if ((STATUS_OBJECT_NAME_NOT_FOUND == Result && '\0' != c) ||
STATUS_NOT_A_DIRECTORY == Result)
if (STATUS_OBJECT_NAME_NOT_FOUND != Result || '\0' != c)
Result = STATUS_OBJECT_PATH_NOT_FOUND;
return Result;
}
@ -1301,3 +1272,38 @@ no_symlink_exit:
PIoStatus->Information = ReparseData->ReparseTag;
return STATUS_REPARSE;
}
FSP_API NTSTATUS FspFileSystemCanReplaceReparsePoint(
PVOID CurrentReparseData, SIZE_T CurrentReparseDataSize,
PVOID ReplaceReparseData, SIZE_T ReplaceReparseDataSize)
{
if (sizeof(ULONG) > CurrentReparseDataSize ||
sizeof(ULONG) > ReplaceReparseDataSize)
return STATUS_IO_REPARSE_DATA_INVALID; /* should not happen! */
else if (*(PULONG)CurrentReparseData != *(PULONG)ReplaceReparseData)
return STATUS_IO_REPARSE_TAG_MISMATCH;
else if (!IsReparseTagMicrosoft(*(PULONG)CurrentReparseData) && (
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > CurrentReparseDataSize ||
REPARSE_GUID_DATA_BUFFER_HEADER_SIZE > ReplaceReparseDataSize ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data1 !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data1 ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data2 !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data2 ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data3 !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data3 ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[0] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[0] ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[1] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[1] ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[2] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[2] ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[3] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[3] ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[4] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[4] ||
((PREPARSE_GUID_DATA_BUFFER)CurrentReparseData)->ReparseGuid.Data4[5] !=
((PREPARSE_GUID_DATA_BUFFER)ReplaceReparseData)->ReparseGuid.Data4[5]))
return STATUS_REPARSE_ATTRIBUTE_CONFLICT;
else
return STATUS_SUCCESS;
}

View File

@ -183,6 +183,86 @@ NTSTATUS fsp_fuse_op_leave(FSP_FILE_SYSTEM *FileSystem,
return STATUS_SUCCESS;
}
static NTSTATUS fsp_fuse_intf_NewHiddenName(FSP_FILE_SYSTEM *FileSystem,
char *PosixPath, char **PPosixHiddenPath)
{
struct fuse *f = FileSystem->UserContext;
NTSTATUS Result;
char *PosixHiddenPath = 0;
char *p, *lastp;
size_t Size;
RPC_STATUS RpcStatus;
union
{
struct { UINT32 V[4]; } Values;
UUID Uuid;
} UuidBuf;
struct fuse_stat stbuf;
int err, maxtries = 3;
*PPosixHiddenPath = 0;
p = PosixPath;
for (;;)
{
while ('/' == *p)
p++;
lastp = p;
while ('/' != *p)
{
if ('\0' == *p)
goto loopend;
p++;
}
}
loopend:;
Size = lastp - PosixPath + sizeof ".fuse_hidden0123456789abcdef";
PosixHiddenPath = MemAlloc(Size);
if (0 == PosixHiddenPath)
{
Result = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
memcpy(PosixHiddenPath, PosixPath, lastp - PosixPath);
do
{
RpcStatus = UuidCreate(&UuidBuf.Uuid);
if (S_OK != RpcStatus && RPC_S_UUID_LOCAL_ONLY != RpcStatus)
{
Result = STATUS_INTERNAL_ERROR;
goto exit;
}
wsprintfA(PosixHiddenPath + (lastp - PosixPath),
".fuse_hidden%08lx%08lx",
UuidBuf.Values.V[0] ^ UuidBuf.Values.V[2],
UuidBuf.Values.V[1] ^ UuidBuf.Values.V[3]);
memset(&stbuf, 0, sizeof stbuf);
if (0 != f->ops.getattr)
err = f->ops.getattr(PosixPath, (void *)&stbuf);
else
err = -ENOSYS;
} while (0 == err && 0 < --maxtries);
if (0 == err)
{
Result = STATUS_DEVICE_BUSY; // current EBUSY mapping
goto exit;
}
*PPosixHiddenPath = PosixHiddenPath;
Result = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(Result))
MemFree(PosixHiddenPath);
return Result;
}
static NTSTATUS fsp_fuse_intf_GetFileInfoEx(FSP_FILE_SYSTEM *FileSystem,
const char *PosixPath, struct fuse_file_info *fi,
PUINT32 PUid, PUINT32 PGid, PUINT32 PMode,
@ -321,7 +401,7 @@ static NTSTATUS fsp_fuse_intf_GetReparsePointEx(
return STATUS_INVALID_DEVICE_REQUEST;
err = f->ops.readlink(PosixPath, PosixTargetPath, sizeof PosixTargetPath);
if (EINVAL/* same on MSVC and Cygwin */ == err)
if (-EINVAL/* same on MSVC and Cygwin */ == err)
{
Result = STATUS_NOT_A_REPARSE_POINT;
goto exit;
@ -1653,16 +1733,19 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
struct fsp_fuse_file_desc *filedesc =
(PVOID)(UINT_PTR)Request->Req.FileSystemControl.UserContext2;
WCHAR TargetPath[FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)];
char *PosixTargetPath = 0;
char *PosixTargetPath = 0, *PosixHiddenPath = 0;
int err;
NTSTATUS Result;
if (0 == f->ops.symlink)
if (0 == f->ops.symlink || 0 == f->ops.rename || 0 == f->ops.unlink)
return STATUS_INVALID_DEVICE_REQUEST;
/* were we asked to delete the reparse point? no can do! */
if (0 == Buffer)
return STATUS_ACCESS_DENIED;
/* FUSE cannot make a directory into a symlink */
if (filedesc->IsDirectory)
{
Result = STATUS_ACCESS_DENIED;
goto exit;
}
/* is this an absolute path? */
if (Size > 4 * sizeof(WCHAR) &&
@ -1691,22 +1774,64 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
if (!NT_SUCCESS(Result))
goto exit;
err = f->ops.symlink(PosixTargetPath, filedesc->PosixPath);
/*
* How we implement this is probably one of the worst aspects of this FUSE implementation.
*
* In Windows a CreateSymbolicLink is the sequence of the following:
* Create
* DeviceIoControl(FSCTL_SET_REPARSE_POINT)
* Cleanup
* Close
*
* The Create call creates the new file and the DeviceIoControl(FSCTL_SET_REPARSE_POINT)
* call is supposed to convert it into a reparse point. However FUSE symlink() will fail
* with -EEXIST in this case.
*
* We must therefore find a solution using rename, which is unreliable and error-prone.
* Note that this will also result in a change of the inode number for the symlink!
*/
Result = fsp_fuse_intf_NewHiddenName(FileSystem, filedesc->PosixPath, &PosixHiddenPath);
if (!NT_SUCCESS(Result))
goto exit;
err = f->ops.symlink(PosixTargetPath, PosixHiddenPath);
if (0 != err)
{
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
goto exit;
}
err = f->ops.rename(PosixHiddenPath, filedesc->PosixPath);
if (0 != err)
{
/* on failure unlink "hidden" symlink */
f->ops.unlink(PosixHiddenPath);
Result = fsp_fuse_ntstatus_from_errno(f->env, err);
goto exit;
}
Result = STATUS_SUCCESS;
exit:
MemFree(PosixHiddenPath);
if (0 != PosixTargetPath)
FspPosixDeletePath(PosixTargetPath);
return Result;
}
static NTSTATUS fsp_fuse_intf_DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode,
PWSTR FileName, PVOID Buffer, SIZE_T Size)
{
/* we were asked to delete the reparse point? no can do! */
return STATUS_ACCESS_DENIED;
}
FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
{
fsp_fuse_intf_GetVolumeInfo,
@ -1731,4 +1856,5 @@ FSP_FILE_SYSTEM_INTERFACE fsp_fuse_intf =
fsp_fuse_intf_ResolveReparsePoints,
fsp_fuse_intf_GetReparsePoint,
fsp_fuse_intf_SetReparsePoint,
fsp_fuse_intf_DeleteReparsePoint,
};

View File

@ -339,8 +339,6 @@ static NTSTATUS FspFsvolCreateNoLock(
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT);
if (CreateOptions & FILE_DIRECTORY_FILE)
SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY);
if (CreateOptions & FILE_OPEN_REPARSE_POINT)
SetFlag(FileAttributes, FILE_ATTRIBUTE_REPARSE_POINT);
/*
* The new request is associated with our IRP. Go ahead and associate our FileNode/FileDesc

View File

@ -1007,25 +1007,66 @@ static NTSTATUS SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
PVOID FileNode0,
PWSTR FileName, PVOID Buffer, SIZE_T Size)
{
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
PVOID ReparseData;
NTSTATUS Result;
if (0 == (FileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
return STATUS_NOT_A_REPARSE_POINT;
if (MemfsFileNodeMapHasChild(Memfs->FileNodeMap, FileNode))
return STATUS_DIRECTORY_NOT_EMPTY;
if (0 != FileNode->ReparseData)
{
Result = FspFileSystemCanReplaceReparsePoint(
FileNode->ReparseData, FileNode->ReparseDataSize,
Buffer, Size);
if (!NT_SUCCESS(Result))
return Result;
}
ReparseData = realloc(FileNode->ReparseData, Size);
if (0 == ReparseData)
if (0 == ReparseData && 0 != Size)
return STATUS_INSUFFICIENT_RESOURCES;
/* the first field in a reparse buffer is the reparse tag */
FileNode->FileInfo.ReparseTag = 0 != Buffer ? *(PULONG)Buffer : 0;
FileNode->FileInfo.FileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
FileNode->FileInfo.ReparseTag = *(PULONG)Buffer;
/* the first field in a reparse buffer is the reparse tag */
FileNode->ReparseDataSize = Size;
FileNode->ReparseData = ReparseData;
memcpy(FileNode->ReparseData, Buffer, Size);
return STATUS_SUCCESS;
}
static NTSTATUS DeleteReparsePoint(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request,
PVOID FileNode0,
PWSTR FileName, PVOID Buffer, SIZE_T Size)
{
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
NTSTATUS Result;
if (0 != FileNode->ReparseData)
{
Result = FspFileSystemCanReplaceReparsePoint(
FileNode->ReparseData, FileNode->ReparseDataSize,
Buffer, Size);
if (!NT_SUCCESS(Result))
return Result;
}
else
return STATUS_NOT_A_REPARSE_POINT;
free(FileNode->ReparseData);
FileNode->FileInfo.FileAttributes &= ~FILE_ATTRIBUTE_REPARSE_POINT;
FileNode->FileInfo.ReparseTag = 0;
FileNode->ReparseDataSize = 0;
FileNode->ReparseData = 0;
return STATUS_SUCCESS;
}
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
{
GetVolumeInfo,
@ -1050,6 +1091,7 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
ResolveReparsePoints,
GetReparsePoint,
SetReparsePoint,
DeleteReparsePoint,
};
NTSTATUS MemfsCreate(