sys,dll: reparse point testing

This commit is contained in:
Bill Zissimopoulos 2016-09-10 23:00:55 -07:00
parent 0d25e73364
commit af2cc10c15
8 changed files with 171 additions and 112 deletions

View File

@ -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
{ {

View File

@ -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;

View File

@ -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);

View File

@ -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();
} }
} }

View File

@ -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);

View File

@ -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:
; ;

View File

@ -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;

View File

@ -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);