mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
sys,dll: symbolic link testing
This commit is contained in:
parent
997476f015
commit
bd0acf2289
@ -1056,87 +1056,87 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
FSP_FILE_SYSTEM *FileSystem, PVOID Context,
|
||||||
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
PWSTR FileName, BOOLEAN IsDirectory, PVOID Buffer, PSIZE_T PSize),
|
||||||
PVOID Context,
|
PVOID Context,
|
||||||
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent,
|
PWSTR FileName, UINT32 ReparsePointIndex, BOOLEAN ResolveLastPathComponent0,
|
||||||
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
PIO_STATUS_BLOCK PIoStatus, PVOID Buffer, PSIZE_T PSize)
|
||||||
{
|
{
|
||||||
WCHAR c, *p, *lastp;
|
PWSTR TargetPath, RemainderPath, LastPathComponent, NewRemainderPath, ReparseTargetPath;
|
||||||
PWSTR TargetPath, TargetPathEnd, ReparseTargetPath;
|
WCHAR RemainderChar;
|
||||||
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, ReparseTargetPathLength, MaxTries = 32;
|
SIZE_T ReparseDataSize, RemainderPathSize, ReparseTargetPathLength;
|
||||||
|
BOOLEAN ResolveLastPathComponent;
|
||||||
|
ULONG MaxTries = 32;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
TargetPath = Buffer;
|
TargetPath = Buffer;
|
||||||
TargetPathEnd = TargetPath + *PSize / sizeof(WCHAR);
|
RemainderPathSize = (lstrlenW(FileName) + 1) * sizeof(WCHAR);
|
||||||
Size = (lstrlenW(FileName) + 1) * sizeof(WCHAR);
|
if (RemainderPathSize > *PSize)
|
||||||
if (Size > *PSize)
|
|
||||||
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
memcpy(TargetPath, FileName, Size);
|
memcpy(TargetPath, FileName, RemainderPathSize);
|
||||||
|
|
||||||
p = TargetPath + ReparsePointIndex;
|
ResolveLastPathComponent = ResolveLastPathComponent0;
|
||||||
c = *p;
|
RemainderPath = TargetPath + ReparsePointIndex;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
while (L'\\' == *p)
|
while (L'\\' == *RemainderPath)
|
||||||
p++;
|
RemainderPath++;
|
||||||
lastp = p;
|
LastPathComponent = RemainderPath;
|
||||||
while (L'\\' != *p)
|
while (L'\\' != *RemainderPath)
|
||||||
{
|
{
|
||||||
if (L'\0' == *p)
|
if (L'\0' == *RemainderPath)
|
||||||
{
|
{
|
||||||
if (!ResolveLastPathComponent)
|
if (!ResolveLastPathComponent)
|
||||||
goto exit;
|
goto exit;
|
||||||
ResolveLastPathComponent = FALSE;
|
ResolveLastPathComponent = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p++;
|
RemainderPath++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle dot and dotdot! */
|
/* handle dot and dotdot! */
|
||||||
if (L'.' == lastp[0])
|
if (L'.' == LastPathComponent[0])
|
||||||
{
|
{
|
||||||
if (p == lastp + 1)
|
if (RemainderPath == LastPathComponent + 1)
|
||||||
/* dot */
|
/* dot */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (L'.' == lastp[1] && p == lastp + 2)
|
if (L'.' == LastPathComponent[1] && RemainderPath == LastPathComponent + 2)
|
||||||
{
|
{
|
||||||
/* dotdot */
|
/* dotdot */
|
||||||
p = lastp;
|
RemainderPath = LastPathComponent;
|
||||||
while (TargetPath < p)
|
while (TargetPath < RemainderPath)
|
||||||
{
|
{
|
||||||
p--;
|
RemainderPath--;
|
||||||
if (L'\\' != *p)
|
if (L'\\' != *RemainderPath)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (TargetPath < p)
|
while (TargetPath < RemainderPath)
|
||||||
{
|
{
|
||||||
p--;
|
RemainderPath--;
|
||||||
if (L'\\' == *p)
|
if (L'\\' == *RemainderPath)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *p;
|
RemainderChar = *RemainderPath; *RemainderPath = L'\0';
|
||||||
*p = L'\0';
|
ReparseDataSize = sizeof ReparseDataBuf;
|
||||||
Size = sizeof ReparseDataBuf;
|
Result = GetReparsePointByName(FileSystem, Context, TargetPath, '\0' != RemainderChar,
|
||||||
Result = GetReparsePointByName(FileSystem, Context, TargetPath, '\0' != c,
|
ReparseData, &ReparseDataSize);
|
||||||
ReparseData, &Size);
|
*RemainderPath = RemainderChar;
|
||||||
*p = c;
|
|
||||||
|
|
||||||
if (STATUS_NOT_A_REPARSE_POINT == Result)
|
if (STATUS_NOT_A_REPARSE_POINT == Result)
|
||||||
/* it was not a reparse point; continue */
|
/* it was not a reparse point; continue */
|
||||||
continue;
|
continue;
|
||||||
else if (!NT_SUCCESS(Result))
|
else if (!NT_SUCCESS(Result))
|
||||||
{
|
{
|
||||||
if (STATUS_OBJECT_NAME_NOT_FOUND != Result || '\0' != c)
|
if (STATUS_OBJECT_NAME_NOT_FOUND != Result || '\0' != RemainderChar)
|
||||||
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
Result = STATUS_OBJECT_PATH_NOT_FOUND;
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -1162,30 +1162,38 @@ FSP_API NTSTATUS FspFileSystemResolveReparsePoints(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
/* if device relative symlink replace whole path; else replace last path component */
|
/* if device relative symlink replace whole path; else replace last path component */
|
||||||
p = ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0] ?
|
NewRemainderPath = ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0] ?
|
||||||
TargetPath : lastp;
|
TargetPath : LastPathComponent;
|
||||||
|
|
||||||
if (ReparseTargetPathLength + sizeof(WCHAR) > (TargetPathEnd - p) * sizeof(WCHAR))
|
RemainderPathSize = (lstrlenW(RemainderPath) + 1) * sizeof(WCHAR);
|
||||||
|
if (NewRemainderPath + (ReparseTargetPathLength + RemainderPathSize) / sizeof(WCHAR) >
|
||||||
|
TargetPath + *PSize / sizeof(WCHAR))
|
||||||
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
memcpy(p, ReparseTargetPath, ReparseTargetPathLength);
|
/* move remainder path to its new position */
|
||||||
p[ReparseTargetPathLength / sizeof(WCHAR)] = L'\0';
|
memmove(NewRemainderPath + ReparseTargetPathLength, RemainderPath, RemainderPathSize);
|
||||||
|
|
||||||
|
/* copy symlink target */
|
||||||
|
memcpy(NewRemainderPath, ReparseTargetPath, ReparseTargetPathLength);
|
||||||
|
|
||||||
|
ResolveLastPathComponent = ResolveLastPathComponent0;
|
||||||
|
RemainderPath = NewRemainderPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
*PSize = (PUINT8)p - (PUINT8)TargetPath;
|
*PSize = (PUINT8)RemainderPath - (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;
|
||||||
|
|
||||||
reparse_data_exit:
|
reparse_data_exit:
|
||||||
if (Size > *PSize)
|
if (ReparseDataSize > *PSize)
|
||||||
return IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag ?
|
return IO_REPARSE_TAG_SYMLINK != ReparseData->ReparseTag ?
|
||||||
STATUS_IO_REPARSE_DATA_INVALID : STATUS_REPARSE_POINT_NOT_RESOLVED;
|
STATUS_IO_REPARSE_DATA_INVALID : STATUS_REPARSE_POINT_NOT_RESOLVED;
|
||||||
|
|
||||||
*PSize = Size;
|
*PSize = ReparseDataSize;
|
||||||
memcpy(Buffer, ReparseData, Size);
|
memcpy(Buffer, ReparseData, ReparseDataSize);
|
||||||
|
|
||||||
PIoStatus->Status = STATUS_REPARSE;
|
PIoStatus->Status = STATUS_REPARSE;
|
||||||
PIoStatus->Information = ReparseData->ReparseTag;
|
PIoStatus->Information = ReparseData->ReparseTag;
|
||||||
|
@ -485,7 +485,7 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
FSP_FILE_NODE *FileNode = FileDesc->FileNode;
|
||||||
FSP_FILE_NODE *OpenedFileNode;
|
FSP_FILE_NODE *OpenedFileNode;
|
||||||
PREPARSE_DATA_BUFFER ReparseData;
|
PREPARSE_DATA_BUFFER ReparseData;
|
||||||
UNICODE_STRING ReparseTargetPrefix, ReparseTargetPath;
|
UNICODE_STRING ReparseTargetPrefix0, ReparseTargetPrefix1, ReparseTargetPath;
|
||||||
|
|
||||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||||
{
|
{
|
||||||
@ -514,14 +514,15 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
* path. Prefix it with our device name and send it to the IO Manager.
|
* 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
|
* 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,
|
* symbolic link reparse buffer. In this case send the target path to the IO Manager.
|
||||||
* and prefix it with our device name depending on SYMLINK_FLAG_RELATIVE.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IO_REPARSE == Response->IoStatus.Information)
|
if (IO_REPARSE == Response->IoStatus.Information)
|
||||||
{
|
{
|
||||||
RtlCopyMemory(&ReparseTargetPrefix, &FsvolDeviceExtension->VolumeName,
|
RtlCopyMemory(&ReparseTargetPrefix0, &FsvolDeviceExtension->VolumeName,
|
||||||
sizeof ReparseTargetPrefix);
|
sizeof ReparseTargetPrefix0);
|
||||||
|
RtlCopyMemory(&ReparseTargetPrefix1, &FsvolDeviceExtension->VolumePrefix,
|
||||||
|
sizeof ReparseTargetPrefix1);
|
||||||
|
|
||||||
ReparseTargetPath.Length = ReparseTargetPath.MaximumLength =
|
ReparseTargetPath.Length = ReparseTargetPath.MaximumLength =
|
||||||
Response->Rsp.Create.Reparse.FileName.Size;
|
Response->Rsp.Create.Reparse.FileName.Size;
|
||||||
@ -529,7 +530,9 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
(PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
|
(PVOID)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset);
|
||||||
|
|
||||||
if ((PUINT8)ReparseTargetPath.Buffer + ReparseTargetPath.Length >
|
if ((PUINT8)ReparseTargetPath.Buffer + ReparseTargetPath.Length >
|
||||||
(PUINT8)Response + Response->Size || 0 == ReparseTargetPath.Length)
|
(PUINT8)Response + Response->Size ||
|
||||||
|
sizeof(WCHAR) > ReparseTargetPath.Length ||
|
||||||
|
L'\\' != ReparseTargetPath.Buffer[0])
|
||||||
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -540,18 +543,18 @@ 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);
|
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
||||||
|
|
||||||
Result = FsRtlValidateReparsePointBuffer(Response->Rsp.Create.Reparse.Data.Size,
|
Result = FsRtlValidateReparsePointBuffer(Response->Rsp.Create.Reparse.Data.Size,
|
||||||
ReparseData);
|
ReparseData);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
FSP_RETURN();
|
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
||||||
|
|
||||||
if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE))
|
if (FlagOn(ReparseData->SymbolicLinkReparseBuffer.Flags, SYMLINK_FLAG_RELATIVE))
|
||||||
RtlZeroMemory(&ReparseTargetPrefix, sizeof ReparseTargetPrefix);
|
FSP_RETURN(Result = STATUS_REPARSE_POINT_NOT_RESOLVED);
|
||||||
else
|
|
||||||
RtlCopyMemory(&ReparseTargetPrefix, &FsvolDeviceExtension->VolumeName,
|
RtlZeroMemory(&ReparseTargetPrefix0, sizeof ReparseTargetPrefix0);
|
||||||
sizeof ReparseTargetPrefix);
|
RtlZeroMemory(&ReparseTargetPrefix1, sizeof ReparseTargetPrefix1);
|
||||||
|
|
||||||
ReparseTargetPath.Buffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
ReparseTargetPath.Buffer = ReparseData->SymbolicLinkReparseBuffer.PathBuffer +
|
||||||
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
|
||||||
@ -559,20 +562,21 @@ NTSTATUS FspFsvolCreateComplete(
|
|||||||
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReparseTargetPrefix.Length + ReparseTargetPath.Length >
|
if (ReparseTargetPrefix0.Length + ReparseTargetPrefix1.Length + ReparseTargetPath.Length >
|
||||||
FileObject->FileName.MaximumLength)
|
FileObject->FileName.MaximumLength)
|
||||||
{
|
{
|
||||||
PVOID Buffer = FspAllocExternal(
|
PVOID Buffer = FspAllocExternal(
|
||||||
ReparseTargetPrefix.Length + ReparseTargetPath.Length);
|
ReparseTargetPrefix0.Length + ReparseTargetPrefix1.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 =
|
FileObject->FileName.MaximumLength =
|
||||||
ReparseTargetPrefix.Length + ReparseTargetPath.Length;
|
ReparseTargetPrefix0.Length + ReparseTargetPrefix1.Length + ReparseTargetPath.Length;
|
||||||
FileObject->FileName.Buffer = Buffer;
|
FileObject->FileName.Buffer = Buffer;
|
||||||
}
|
}
|
||||||
FileObject->FileName.Length = 0;
|
FileObject->FileName.Length = 0;
|
||||||
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPrefix);
|
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPrefix0);
|
||||||
|
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPrefix1);
|
||||||
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPath);
|
RtlAppendUnicodeStringToString(&FileObject->FileName, &ReparseTargetPath);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -145,7 +145,7 @@ static NTSTATUS FspFsvolFileSystemControlReparsePoint(
|
|||||||
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
ReparseTargetPathLength = ReparseData->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||||
|
|
||||||
/* is this an absolute path? determine if target resides on same device as link */
|
/* is this an absolute path? determine if target resides on same device as link */
|
||||||
if (0 == (ReparseData->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) &&
|
if (!FlagOn(ReparseData->SymbolicLinkReparseBuffer.Flags, SYMLINK_FLAG_RELATIVE) &&
|
||||||
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
|
ReparseTargetPathLength >= sizeof(WCHAR) && L'\\' == ReparseTargetPath[0])
|
||||||
{
|
{
|
||||||
UNICODE_STRING TargetObjectName;
|
UNICODE_STRING TargetObjectName;
|
||||||
|
@ -219,23 +219,15 @@ void reparse_nfs_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reparse_symlink_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
static void reparse_symlink_dotest0(ULONG Flags, PWSTR Prefix,
|
||||||
|
PWSTR FilePath, PWSTR LinkPath, PWSTR TargetPath)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
|
||||||
|
|
||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
BOOL Success;
|
BOOL Success;
|
||||||
WCHAR FilePath[MAX_PATH], LinkPath[MAX_PATH];
|
|
||||||
PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH];
|
PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH];
|
||||||
PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf;
|
PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf;
|
||||||
|
|
||||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
Success = CreateSymbolicLinkW(LinkPath, TargetPath, 0);
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
|
||||||
|
|
||||||
StringCbPrintfW(LinkPath, sizeof LinkPath, L"%s%s\\link0",
|
|
||||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
|
||||||
|
|
||||||
Success = CreateSymbolicLinkW(LinkPath, FilePath, 0);
|
|
||||||
if (Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
Handle = CreateFileW(FilePath,
|
Handle = CreateFileW(FilePath,
|
||||||
@ -277,6 +269,29 @@ static void reparse_symlink_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTime
|
|||||||
ASSERT(ERROR_PRIVILEGE_NOT_HELD == GetLastError());
|
ASSERT(ERROR_PRIVILEGE_NOT_HELD == GetLastError());
|
||||||
FspDebugLog(__FUNCTION__ ": need SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\n");
|
FspDebugLog(__FUNCTION__ ": need SE_CREATE_SYMBOLIC_LINK_PRIVILEGE\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reparse_symlink_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
|
||||||
|
WCHAR FilePath[MAX_PATH], LinkPath[MAX_PATH], TargetPath[MAX_PATH];
|
||||||
|
PUINT8 NameInfoBuf[sizeof(FILE_NAME_INFO) + MAX_PATH];
|
||||||
|
PFILE_NAME_INFO PNameInfo = (PVOID)NameInfoBuf;
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
StringCbPrintfW(LinkPath, sizeof LinkPath, L"%s%s\\link0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
|
||||||
|
reparse_symlink_dotest0(Flags, Prefix, FilePath, LinkPath, FilePath);
|
||||||
|
|
||||||
|
StringCbPrintfW(TargetPath, sizeof TargetPath, L"%s\\file0",
|
||||||
|
-1 == Flags ? Prefix + 6 : L"");
|
||||||
|
reparse_symlink_dotest0(Flags, Prefix, FilePath, LinkPath, TargetPath);
|
||||||
|
|
||||||
|
reparse_symlink_dotest0(Flags, Prefix, FilePath, LinkPath, L"file0");
|
||||||
|
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user