mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
sys,dll: reparse point testing
This commit is contained in:
parent
0d25e73364
commit
af2cc10c15
@ -298,7 +298,7 @@ typedef struct
|
|||||||
UINT64 UserContext2;
|
UINT64 UserContext2;
|
||||||
UINT32 FsControlCode;
|
UINT32 FsControlCode;
|
||||||
FSP_FSCTL_TRANSACT_BUF Buffer;
|
FSP_FSCTL_TRANSACT_BUF Buffer;
|
||||||
UINT32 TargetOnFileSystem:1;/* the target of the symbolic link is on this file system */
|
UINT16 TargetOnFileSystem; /* the target of the symbolic link is on this file system */
|
||||||
} FileSystemControl;
|
} FileSystemControl;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -1060,21 +1060,21 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
{
|
{
|
||||||
WCHAR c, *p, *lastp;
|
WCHAR c, *p, *lastp;
|
||||||
PWSTR TargetPath, TargetPathEnd, TargetLink;
|
PWSTR TargetPath, TargetPathEnd, ReparseTargetPath;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
REPARSE_DATA_BUFFER V;
|
REPARSE_DATA_BUFFER V;
|
||||||
UINT8 B[FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX];
|
UINT8 B[FSP_FSCTL_TRANSACT_RSP_BUFFER_SIZEMAX];
|
||||||
} ReparseDataBuf;
|
} ReparseDataBuf;
|
||||||
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
|
PREPARSE_DATA_BUFFER ReparseData = &ReparseDataBuf.V;
|
||||||
SIZE_T Size, MaxTries = 32;
|
SIZE_T Size, ReparseTargetPathLength, MaxTries = 32;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
TargetPath = Buffer;
|
TargetPath = Buffer;
|
||||||
TargetPathEnd = TargetPath + *PSize / sizeof(WCHAR);
|
TargetPathEnd = TargetPath + *PSize / sizeof(WCHAR);
|
||||||
Size = (lstrlenW(FileName) + 1) * sizeof(WCHAR);
|
Size = (lstrlenW(FileName) + 1) * sizeof(WCHAR);
|
||||||
if (Size > *PSize)
|
if (Size > *PSize)
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
memcpy(TargetPath, FileName, Size);
|
memcpy(TargetPath, FileName, Size);
|
||||||
|
|
||||||
p = TargetPath + ReparsePointIndex;
|
p = TargetPath + ReparsePointIndex;
|
||||||
@ -1143,59 +1143,44 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
/* found a reparse point */
|
/* found a reparse point */
|
||||||
|
|
||||||
|
if (IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag)
|
||||||
|
/* not a symlink; return the full reparse point! */
|
||||||
|
goto reparse_data_exit;
|
||||||
|
|
||||||
|
ReparseTargetPath = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
||||||
|
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
|
||||||
|
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
|
||||||
|
/* absolute symlink; return the full reparse point! */
|
||||||
|
goto reparse_data_exit;
|
||||||
|
|
||||||
if (0 == --MaxTries)
|
if (0 == --MaxTries)
|
||||||
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
if (IO_REPARSE_TAG_SYMLINK == ReparseData->ReparseTag)
|
|
||||||
{
|
|
||||||
TargetLink = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
|
||||||
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
|
||||||
Size = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* not a symlink; return the full reparse point! */
|
|
||||||
if (Size > *PSize)
|
|
||||||
return STATUS_IO_REPARSE_DATA_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 */
|
/* relative symlink; replace last path component seen */
|
||||||
if (Size + sizeof(WCHAR) > (TargetPathEnd - lastp) * sizeof(WCHAR))
|
if (ReparseTargetPathLength + sizeof(WCHAR) > (TargetPathEnd - lastp) * sizeof(WCHAR))
|
||||||
return STATUS_OBJECT_NAME_INVALID;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
memcpy(lastp, TargetLink, Size);
|
memcpy(lastp, ReparseTargetPath, ReparseTargetPathLength);
|
||||||
lastp[Size / sizeof(WCHAR)] = L'\0';
|
lastp[ReparseTargetPathLength / sizeof(WCHAR)] = L'\0';
|
||||||
p = lastp;
|
p = lastp;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
*PSize = (PUINT8)p - (PUINT8)TargetPath;
|
*PSize = (PUINT8)p - (PUINT8)TargetPath;
|
||||||
|
|
||||||
PIoStatus->Status = STATUS_REPARSE;
|
PIoStatus->Status = STATUS_REPARSE;
|
||||||
PIoStatus->Information = 0/*IO_REPARSE*/;
|
PIoStatus->Information = 0/*IO_REPARSE*/;
|
||||||
return STATUS_REPARSE;
|
return STATUS_REPARSE;
|
||||||
|
|
||||||
no_symlink_exit:
|
reparse_data_exit:
|
||||||
|
if (Size > *PSize)
|
||||||
|
return IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag ?
|
||||||
|
STATUS_IO_REPARSE_DATA_INVALID : STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
*PSize = Size;
|
*PSize = Size;
|
||||||
|
memcpy(Buffer, ReparseData, Size);
|
||||||
|
|
||||||
PIoStatus->Status = STATUS_REPARSE;
|
PIoStatus->Status = STATUS_REPARSE;
|
||||||
PIoStatus->Information = ReparseData->ReparseTag;
|
PIoStatus->Information = ReparseData->ReparseTag;
|
||||||
return STATUS_REPARSE;
|
return STATUS_REPARSE;
|
||||||
|
@ -2005,27 +2005,20 @@ static NTSTATUS fsp_fuse_intf_SetReparsePoint(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
|
||||||
/* is this an absolute path? */
|
/* is this an absolute path? */
|
||||||
if (ReparseTargetPathLength > 4 * sizeof(WCHAR) &&
|
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
|
||||||
'\\' == ReparseTargetPath[0] &&
|
|
||||||
'?' == ReparseTargetPath[1] &&
|
|
||||||
'?' == ReparseTargetPath[2] &&
|
|
||||||
'\\' == ReparseTargetPath[3])
|
|
||||||
{
|
{
|
||||||
/* we do not support absolute paths that point outside this file system */
|
/* we do not support absolute paths that point outside this file system */
|
||||||
if (!Request->Req.FileSystemControl.TargetOnFileSystem)
|
if (0 == Request->Req.FileSystemControl.TargetOnFileSystem)
|
||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
|
||||||
|
|
||||||
/* the first path component is assumed to be the device name; skip it! */
|
ReparseTargetPath += Request->Req.FileSystemControl.TargetOnFileSystem / sizeof(WCHAR);
|
||||||
ReparseTargetPath += 4;
|
ReparseTargetPathLength -= Request->Req.FileSystemControl.TargetOnFileSystem;
|
||||||
ReparseTargetPathLength -= 4 * sizeof(WCHAR);
|
}
|
||||||
while (0 < ReparseTargetPathLength && L'\\' != *ReparseTargetPath)
|
|
||||||
ReparseTargetPathLength--, ReparseTargetPath++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReparseTargetPath = (PVOID)(ReparseData->GenericReparseBuffer.DataBuffer + 8);
|
ReparseTargetPath = (PVOID)(ReparseData->GenericReparseBuffer.DataBuffer + 8);
|
||||||
ReparseTargetPathLength = ReparseData->ReparseDataLength - sizeof(UINT64);
|
ReparseTargetPathLength = ReparseData->ReparseDataLength - 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(TargetPath, ReparseTargetPath, ReparseTargetPathLength);
|
memcpy(TargetPath, ReparseTargetPath, ReparseTargetPathLength);
|
||||||
|
@ -486,8 +486,8 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
FSP_FILE_DESC *FileDesc = FspIopRequestContext(Request, RequestFileDesc);
|
||||||
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
||||||
FSP_FILE_NODE *OpenedFileNode;
|
FSP_FILE_NODE *OpenedFileNode;
|
||||||
UNICODE_STRING ReparseFileName;
|
|
||||||
PREPARSE_DATA_BUFFER ReparseData;
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
|
UNICODE_STRING ReparseTargetPrefix, ReparseTargetPath;
|
||||||
|
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
{
|
{
|
||||||
@ -505,32 +505,74 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
if (IO_REMOUNT == Response->IoStatus.Information)
|
if (IO_REMOUNT == Response->IoStatus.Information)
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Information = IO_REMOUNT;
|
Irp->IoStatus.Information = IO_REMOUNT;
|
||||||
Result = STATUS_REPARSE;
|
FSP_RETURN(Result = STATUS_REPARSE);
|
||||||
FSP_RETURN();
|
|
||||||
}
|
}
|
||||||
else if (IO_REPARSE == Response->IoStatus.Information)
|
else
|
||||||
|
if (IO_REPARSE == Response->IoStatus.Information ||
|
||||||
|
IO_REPARSE_TAG_SYMLINK == Response->IoStatus.Information)
|
||||||
{
|
{
|
||||||
ReparseFileName.Buffer =
|
/*
|
||||||
(PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
|
* IO_REPARSE means that the user-mode file system has returned a device-relative
|
||||||
ReparseFileName.Length = ReparseFileName.MaximumLength =
|
* path. Prefix it with our device name and send it to the IO Manager.
|
||||||
|
*
|
||||||
|
* IO_REPARSE_TAG_SYMLINK means that the user-mode file system has returned a full
|
||||||
|
* symbolic link reparse buffer. In this case send the target path to the IO Manager
|
||||||
|
* without prefixing it with our device name as it is expected to be absolute in the
|
||||||
|
* NT namespace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (IO_REPARSE == Response->IoStatus.Information)
|
||||||
|
{
|
||||||
|
RtlCopyMemory(&ReparseTargetPrefix, &FsvolDeviceExtension->VolumeName,
|
||||||
|
sizeof ReparseTargetPrefix);
|
||||||
|
|
||||||
|
ReparseTargetPath.Length = ReparseTargetPath.MaximumLength =
|
||||||
Response->Rsp.Create.Reparse.FileName.Size;
|
Response->Rsp.Create.Reparse.FileName.Size;
|
||||||
|
ReparseTargetPath.Buffer =
|
||||||
|
(PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
|
||||||
|
|
||||||
if ((PUINT8)ReparseFileName.Buffer + ReparseFileName.Length >
|
if ((PUINT8)ReparseTargetPath.Buffer + ReparseTargetPath.Length >
|
||||||
(PUINT8)Response + Response->Size ||
|
(PUINT8)Response + Response->Size || 0 == ReparseTargetPath.Length)
|
||||||
0 == ReparseFileName.Length)
|
|
||||||
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
||||||
|
}
|
||||||
if (ReparseFileName.Length > FileObject->FileName.MaximumLength)
|
else
|
||||||
{
|
{
|
||||||
PVOID Buffer = FspAllocExternal(ReparseFileName.Length);
|
ASSERT(IO_REPARSE_TAG_SYMLINK == Response->IoStatus.Information);
|
||||||
|
|
||||||
|
ReparseData = (PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.Data.Offset);
|
||||||
|
|
||||||
|
if ((PUINT8)ReparseData + Response->Rsp.Create.Reparse.Data.Size >
|
||||||
|
(PUINT8)Response + Response->Size)
|
||||||
|
FSP_RETURN(Result = STATUS_IO_REPARSE_DATA_INVALID);
|
||||||
|
|
||||||
|
Result = FsRtlValidateReparsePointBuffer(Response->Rsp.Create.Reparse.Data.Size,
|
||||||
|
ReparseData);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
FSP_RETURN();
|
||||||
|
|
||||||
|
RtlZeroMemory(&ReparseTargetPrefix, sizeof ReparseTargetPrefix);
|
||||||
|
|
||||||
|
ReparseTargetPath.Buffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
||||||
|
ReparseTargetPath.Length = ReparseTargetPath.MaximumLength =
|
||||||
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReparseTargetPrefix.Length + ReparseTargetPath.Length >
|
||||||
|
FileObject->FileName.MaximumLength)
|
||||||
|
{
|
||||||
|
PVOID Buffer = FspAllocExternal(
|
||||||
|
ReparseTargetPrefix.Length + ReparseTargetPath.Length);
|
||||||
if (0 == Buffer)
|
if (0 == Buffer)
|
||||||
FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
|
FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
|
||||||
FspFreeExternal(FileObject->FileName.Buffer);
|
FspFreeExternal(FileObject->FileName.Buffer);
|
||||||
FileObject->FileName.MaximumLength = ReparseFileName.Length;
|
FileObject->FileName.MaximumLength =
|
||||||
|
ReparseTargetPrefix.Length + ReparseTargetPath.Length;
|
||||||
FileObject->FileName.Buffer = Buffer;
|
FileObject->FileName.Buffer = Buffer;
|
||||||
}
|
}
|
||||||
FileObject->FileName.Length = 0;
|
FileObject->FileName.Length = 0;
|
||||||
RtlCopyUnicodeString(&FileObject->FileName, &ReparseFileName);
|
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPrefix);
|
||||||
|
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPath);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The RelatedFileObject does not need to be changed according to:
|
* The RelatedFileObject does not need to be changed according to:
|
||||||
@ -548,8 +590,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Irp->IoStatus.Information = IO_REPARSE;
|
Irp->IoStatus.Information = IO_REPARSE;
|
||||||
Result = STATUS_REPARSE;
|
FSP_RETURN(Result = STATUS_REPARSE);
|
||||||
FSP_RETURN();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -557,10 +598,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
|
|
||||||
if ((PUINT8)ReparseData + Response->Rsp.Create.Reparse.Data.Size >
|
if ((PUINT8)ReparseData + Response->Rsp.Create.Reparse.Data.Size >
|
||||||
(PUINT8)Response + Response->Size)
|
(PUINT8)Response + Response->Size)
|
||||||
{
|
FSP_RETURN(Result = STATUS_IO_REPARSE_DATA_INVALID);
|
||||||
Result = STATUS_IO_REPARSE_DATA_INVALID;
|
|
||||||
FSP_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result = FsRtlValidateReparsePointBuffer(Response->Rsp.Create.Reparse.Data.Size,
|
Result = FsRtlValidateReparsePointBuffer(Response->Rsp.Create.Reparse.Data.Size,
|
||||||
ReparseData);
|
ReparseData);
|
||||||
@ -571,17 +609,13 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
Irp->Tail.Overlay.AuxiliaryBuffer = FspAllocNonPagedExternal(
|
Irp->Tail.Overlay.AuxiliaryBuffer = FspAllocNonPagedExternal(
|
||||||
Response->Rsp.Create.Reparse.Data.Size);
|
Response->Rsp.Create.Reparse.Data.Size);
|
||||||
if (0 == Irp->Tail.Overlay.AuxiliaryBuffer)
|
if (0 == Irp->Tail.Overlay.AuxiliaryBuffer)
|
||||||
{
|
FSP_RETURN(Result = STATUS_INSUFFICIENT_RESOURCES);
|
||||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
FSP_RETURN();
|
|
||||||
}
|
|
||||||
|
|
||||||
RtlCopyMemory(Irp->Tail.Overlay.AuxiliaryBuffer, ReparseData,
|
RtlCopyMemory(Irp->Tail.Overlay.AuxiliaryBuffer, ReparseData,
|
||||||
Response->Rsp.Create.Reparse.Data.Size);
|
Response->Rsp.Create.Reparse.Data.Size);
|
||||||
|
|
||||||
Irp->IoStatus.Information = ReparseData->ReparseTag;
|
Irp->IoStatus.Information = ReparseData->ReparseTag;
|
||||||
Result = STATUS_REPARSE;
|
FSP_RETURN(Result = STATUS_REPARSE);
|
||||||
FSP_RETURN();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,6 +427,8 @@ PVOID FspAllocateIrpMustSucceed(CCHAR StackSize);
|
|||||||
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
||||||
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
|
NTSTATUS FspGetDeviceObjectByName(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
|
PULONG PFileNameIndex, PDEVICE_OBJECT *PDeviceObject);
|
||||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||||
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
NTSTATUS FspBufferUserBuffer(PIRP Irp, ULONG Length, LOCK_OPERATION Operation);
|
||||||
|
@ -109,8 +109,9 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
|
|||||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||||
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||||
PREPARSE_DATA_BUFFER ReparseData;
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
PWSTR PathBuffer;
|
PWSTR ReparseTargetPath;
|
||||||
BOOLEAN TargetOnFileSystem = FALSE;
|
USHORT ReparseTargetPathLength;
|
||||||
|
UINT16 TargetOnFileSystem = 0;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
@ -139,36 +140,28 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
|
|||||||
return STATUS_PRIVILEGE_NOT_HELD;
|
return STATUS_PRIVILEGE_NOT_HELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* determine if target resides on same device as link (convenience for user mode) */
|
ReparseTargetPath = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
PathBuffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
|
||||||
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
||||||
if (ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength > 4 * sizeof(WCHAR) &&
|
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
'\\' == PathBuffer[0] &&
|
|
||||||
'?' == PathBuffer[1] &&
|
/* is this an absolute path? determine if target resides on same device as link */
|
||||||
'?' == PathBuffer[2] &&
|
if (ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
|
||||||
'\\' == PathBuffer[3])
|
|
||||||
{
|
{
|
||||||
UNICODE_STRING TargetDeviceName;
|
UNICODE_STRING TargetObjectName;
|
||||||
PFILE_OBJECT TargetDeviceFile;
|
|
||||||
PDEVICE_OBJECT TargetDeviceObject;
|
PDEVICE_OBJECT TargetDeviceObject;
|
||||||
|
ULONG TargetFileNameIndex;
|
||||||
|
|
||||||
RtlInitEmptyUnicodeString(&TargetDeviceName,
|
TargetObjectName.Length = TargetObjectName.MaximumLength = ReparseTargetPathLength;
|
||||||
PathBuffer,
|
TargetObjectName.Buffer = ReparseTargetPath;
|
||||||
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength);
|
|
||||||
|
|
||||||
/* the first path component is assumed to be the device name */
|
Result = FspGetDeviceObjectByName(&TargetObjectName, FILE_READ_DATA,
|
||||||
TargetDeviceName.Length = 4 * sizeof(WCHAR);
|
&TargetFileNameIndex, &TargetDeviceObject);
|
||||||
while (TargetDeviceName.Length < TargetDeviceName.MaximumLength &&
|
|
||||||
'\\' != TargetDeviceName.Buffer[TargetDeviceName.Length / sizeof(WCHAR)])
|
|
||||||
TargetDeviceName.Length += sizeof(WCHAR);
|
|
||||||
|
|
||||||
Result = IoGetDeviceObjectPointer(&TargetDeviceName,
|
|
||||||
FILE_READ_ATTRIBUTES, &TargetDeviceFile, &TargetDeviceObject);
|
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto target_check_exit;
|
goto target_check_exit;
|
||||||
|
|
||||||
TargetOnFileSystem = IoGetRelatedDeviceObject(FileObject) == TargetDeviceObject;
|
TargetOnFileSystem = IoGetRelatedDeviceObject(FileObject) == TargetDeviceObject ?
|
||||||
ObDereferenceObject(TargetDeviceFile);
|
(UINT16)TargetFileNameIndex : 0;
|
||||||
|
ObDereferenceObject(TargetDeviceObject);
|
||||||
|
|
||||||
target_check_exit:
|
target_check_exit:
|
||||||
;
|
;
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
BOOLEAN FspUnicodePathIsValid(PUNICODE_STRING Path, BOOLEAN AllowStreams);
|
||||||
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
|
||||||
NTSTATUS FspCreateGuid(GUID *Guid);
|
NTSTATUS FspCreateGuid(GUID *Guid);
|
||||||
|
NTSTATUS FspGetDeviceObjectByName(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
|
PULONG PFileNameIndex, PDEVICE_OBJECT *PDeviceObject);
|
||||||
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
NTSTATUS FspSendSetInformationIrp(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||||
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
FILE_INFORMATION_CLASS FileInformationClass, PVOID FileInformation, ULONG Length);
|
||||||
static NTSTATUS FspSendSetInformationIrpCompletion(
|
static NTSTATUS FspSendSetInformationIrpCompletion(
|
||||||
@ -88,6 +90,7 @@ NTSTATUS FspIrpHookNext(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
|
|||||||
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
#pragma alloc_text(PAGE, FspUnicodePathIsValid)
|
||||||
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
|
||||||
#pragma alloc_text(PAGE, FspCreateGuid)
|
#pragma alloc_text(PAGE, FspCreateGuid)
|
||||||
|
#pragma alloc_text(PAGE, FspGetDeviceObjectByName)
|
||||||
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
#pragma alloc_text(PAGE, FspSendSetInformationIrp)
|
||||||
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
#pragma alloc_text(PAGE, FspBufferUserBuffer)
|
||||||
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
#pragma alloc_text(PAGE, FspLockUserBuffer)
|
||||||
@ -243,6 +246,55 @@ NTSTATUS FspCreateGuid(GUID *Guid)
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspGetDeviceObjectByName(PUNICODE_STRING ObjectName, ACCESS_MASK DesiredAccess,
|
||||||
|
PULONG PFileNameIndex, PDEVICE_OBJECT *PDeviceObject)
|
||||||
|
{
|
||||||
|
UNICODE_STRING PartialName;
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||||
|
HANDLE Handle;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
PartialName.Length = 0;
|
||||||
|
PartialName.MaximumLength = ObjectName->Length;
|
||||||
|
PartialName.Buffer = ObjectName->Buffer;
|
||||||
|
|
||||||
|
Result = STATUS_NO_SUCH_DEVICE;
|
||||||
|
while (PartialName.MaximumLength > PartialName.Length)
|
||||||
|
{
|
||||||
|
while (PartialName.MaximumLength > PartialName.Length &&
|
||||||
|
L'\\' == PartialName.Buffer[PartialName.Length / sizeof(WCHAR)])
|
||||||
|
PartialName.Length += sizeof(WCHAR);
|
||||||
|
while (PartialName.MaximumLength > PartialName.Length &&
|
||||||
|
L'\\' != PartialName.Buffer[PartialName.Length / sizeof(WCHAR)])
|
||||||
|
PartialName.Length += sizeof(WCHAR);
|
||||||
|
|
||||||
|
Result = IoGetDeviceObjectPointer(&PartialName, DesiredAccess, &FileObject, PDeviceObject);
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
*PFileNameIndex = PartialName.Length;
|
||||||
|
ObReferenceObject(*PDeviceObject);
|
||||||
|
ObDereferenceObject(FileObject);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes, &PartialName, OBJ_KERNEL_HANDLE, 0, 0);
|
||||||
|
Result = ZwOpenDirectoryObject(&Handle, 0, &ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = ZwOpenSymbolicLinkObject(&Handle, 0, &ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
Result = STATUS_NO_SUCH_DEVICE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ZwClose(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK IoStatus;
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
@ -1153,7 +1153,7 @@ NTSTATUS MemfsCreate(
|
|||||||
VolumeParams.UnicodeOnDisk = 1;
|
VolumeParams.UnicodeOnDisk = 1;
|
||||||
VolumeParams.PersistentAcls = 1;
|
VolumeParams.PersistentAcls = 1;
|
||||||
VolumeParams.ReparsePoints = 1;
|
VolumeParams.ReparsePoints = 1;
|
||||||
VolumeParams.ReparsePointsAccessCheck = 1;
|
VolumeParams.ReparsePointsAccessCheck = 0;
|
||||||
if (0 != VolumePrefix)
|
if (0 != VolumePrefix)
|
||||||
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
wcscpy_s(VolumeParams.Prefix, sizeof VolumeParams.Prefix / sizeof(WCHAR), VolumePrefix);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user