mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys,dll: symbolic link testing
This commit is contained in:
		| @@ -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); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user