From: "Erich E. Hoover" erich.e.hoover@gmail.com
--- dlls/kernelbase/file.c | 2 ++ dlls/ntdll/tests/file.c | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index c02435c0dd3..6c6168cfbe8 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -776,6 +776,8 @@ static UINT get_nt_file_options( DWORD attributes, DWORD creation ) options |= FILE_DELETE_ON_CLOSE; if (attributes & FILE_FLAG_NO_BUFFERING) options |= FILE_NO_INTERMEDIATE_BUFFERING; + if (attributes & FILE_FLAG_OPEN_REPARSE_POINT) + options |= FILE_OPEN_REPARSE_POINT; if (!(attributes & FILE_FLAG_OVERLAPPED)) options |= FILE_SYNCHRONOUS_IO_NONALERT; if (attributes & FILE_FLAG_RANDOM_ACCESS) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 7f8cfdadcd5..bbba116cbe3 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -6470,7 +6470,7 @@ static void test_reparse_points(void) ret = GetFinalPathNameByHandleW( handle2, ret_path, ARRAY_SIZE( ret_path ), VOLUME_NAME_DOS ); ok( ret > 0, "got error %lu\n", GetLastError() ); swprintf( path, ARRAY_SIZE(path), L"\\?\%stestreparse_dirlink", temp_path ); - todo_wine ok( !wcscmp( ret_path, path ), "expected path %s, got %s\n", debugstr_w( path ), debugstr_w( ret_path )); + ok( !wcscmp( ret_path, path ), "expected path %s, got %s\n", debugstr_w( path ), debugstr_w( ret_path )); CloseHandle( handle2 );
status = NtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_DELETE_REPARSE_POINT, NULL, 0, NULL, 0 ); @@ -6541,11 +6541,8 @@ static void test_reparse_points(void) swprintf( path, ARRAY_SIZE(path), L"%s/testreparse_dirlink", temp_path ); handle2 = CreateFileW( path, DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0 ); - todo_wine ok( handle2 != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); - if (handle2 != INVALID_HANDLE_VALUE) - status = NtSetInformationFile( handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation ); - else - status = NtSetInformationFile( handle, &io, &fdi, sizeof(fdi), FileDispositionInformation ); + ok( handle2 != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); + status = NtSetInformationFile( handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation ); ok( !status, "got %#lx\n", status ); CloseHandle( handle2 );
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/kernelbase/file.c | 2 +- dlls/ntdll/tests/file.c | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 6c6168cfbe8..66f2c742530 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -683,7 +683,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH CreateDirectoryW( LPCWSTR path, LPSECURITY_ATTRIBU InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, sa ? sa->lpSecurityDescriptor : NULL ); status = NtCreateFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_CREATE, - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT, NULL, 0 ); if (status == STATUS_SUCCESS) NtClose( handle );
RtlFreeUnicodeString( &nt_name ); diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index bbba116cbe3..c50ba97cd04 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -6528,13 +6528,8 @@ static void test_reparse_points(void) * FILE_OPEN_REPARSE_POINT under the hood. */ swprintf( path, ARRAY_SIZE(path), L"%stestreparse_dirlink", temp_path ); ret = CreateDirectoryW( path, NULL ); - todo_wine ok( ret == FALSE, "got %d\n", ret ); - todo_wine ok( GetLastError() == ERROR_ALREADY_EXISTS, "got error %lu\n", GetLastError() ); - if (ret) - { - ret = RemoveDirectoryW( path ); - ok( ret == TRUE, "got error %lu\n", GetLastError() ); - } + ok( ret == FALSE, "got %d\n", ret ); + ok( GetLastError() == ERROR_ALREADY_EXISTS, "got error %lu\n", GetLastError() );
/* Test FindFirstFile(). */
From: "Erich E. Hoover" erich.e.hoover@gmail.com
--- dlls/kernelbase/file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 66f2c742530..8522992e2ef 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -1030,9 +1030,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH DeleteFileW( LPCWSTR path ) }
InitializeObjectAttributes( &attr, &nameW, OBJ_CASE_INSENSITIVE, 0, NULL ); - status = NtCreateFile(&hFile, SYNCHRONIZE | DELETE, &attr, &io, NULL, 0, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_OPEN, FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE, NULL, 0); + status = NtCreateFile( &hFile, SYNCHRONIZE | DELETE, &attr, &io, NULL, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, + FILE_DELETE_ON_CLOSE | FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT, NULL, 0 ); if (status == STATUS_SUCCESS) status = NtClose(hFile);
RtlFreeUnicodeString( &nameW );
From: "Erich E. Hoover" erich.e.hoover@gmail.com
--- dlls/kernelbase/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 8522992e2ef..79cb99cbe3c 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -3634,7 +3634,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RemoveDirectoryW( LPCWSTR path ) InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); status = NtOpenFile( &handle, DELETE | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT ); RtlFreeUnicodeString( &nt_name );
if (!status)
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/tests/file.c | 87 +++++++++++++++++++++++------------------ dlls/ntdll/unix/file.c | 52 ++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 37 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index c50ba97cd04..0b4c7503511 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -6701,18 +6701,21 @@ static void test_reparse_points(void) ret = LookupPrivilegeValueA( NULL, "SeCreateSymbolicLinkPrivilege", &luid ); todo_wine ok( ret == TRUE, "got error %lu\n", GetLastError() );
- privs.PrivilegeCount = 1; - privs.Privileges[0].Luid = luid; - privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - ret = AdjustTokenPrivileges( token, FALSE, &privs, 0, NULL, NULL ); - ok( ret == TRUE, "got error %lu\n", GetLastError() ); - if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + if (ret) { - todo_wine win_skip("Insufficient permissions to perform symlink tests.\n"); + privs.PrivilegeCount = 1; + privs.Privileges[0].Luid = luid; + privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + ret = AdjustTokenPrivileges( token, FALSE, &privs, 0, NULL, NULL ); + ok( ret == TRUE, "got error %lu\n", GetLastError() ); + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) + { + win_skip("Insufficient permissions to perform symlink tests.\n"); + CloseHandle( token ); + goto out; + } CloseHandle( token ); - goto out; } - CloseHandle( token );
RtlInitUnicodeString( &nameW, L"testreparse_filelink" ); status = NtCreateFile( &handle, GENERIC_ALL, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, @@ -6725,7 +6728,7 @@ static void test_reparse_points(void)
status = NtCreateFile( &handle2, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, 0, NULL, 0 ); - ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status );
data_size = init_reparse_symlink( &data, L"testreparse_dir", SYMLINK_FLAG_RELATIVE ); status = NtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_SET_REPARSE_POINT, data, data_size, NULL, 0 ); @@ -6733,7 +6736,7 @@ static void test_reparse_points(void)
status = NtCreateFile( &handle2, GENERIC_READ, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, 0, NULL, 0 ); - ok( status == STATUS_FILE_IS_A_DIRECTORY || broken(!status) /* < Win10 1709 */, "got %#lx\n", status ); + todo_wine ok( status == STATUS_FILE_IS_A_DIRECTORY || broken(!status) /* < Win10 1709 */, "got %#lx\n", status ); if (!status) NtClose( handle2 );
data_size = init_reparse_symlink( &data, L"testreparse_file\", SYMLINK_FLAG_RELATIVE ); @@ -6796,7 +6799,7 @@ static void test_reparse_points(void) * in the file. The status here is rather misleading, of course. */ data->ReparseDataLength = data_size - offsetof( REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer ); status = NtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_SET_REPARSE_POINT, data, data_size, NULL, 0 ); - ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status );
SetFilePointer( handle, 0, 0, FILE_BEGIN ); ret = SetEndOfFile( handle ); @@ -6870,20 +6873,20 @@ static void test_reparse_points(void) ok( handle2 != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); status = NtQueryInformationFile( handle2, &io, &tag_info, sizeof(tag_info), FileAttributeTagInformation ); ok( !status, "got %#lx\n", status ); - ok( tag_info.FileAttributes == (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_REPARSE_POINT), + todo_wine ok( tag_info.FileAttributes == (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_REPARSE_POINT), "got attributes %#lx\n", tag_info.FileAttributes ); - ok( tag_info.ReparseTag == IO_REPARSE_TAG_SYMLINK, "got tag %#lx\n", tag_info.ReparseTag ); + todo_wine ok( tag_info.ReparseTag == IO_REPARSE_TAG_SYMLINK, "got tag %#lx\n", tag_info.ReparseTag ); status = NtQueryInformationFile( handle2, &io, &std_info, sizeof(std_info), FileStandardInformation ); ok( !status, "got %#lx\n", status ); - ok( !std_info.AllocationSize.QuadPart, "got size %#I64x\n", std_info.AllocationSize.QuadPart ); - ok( !std_info.EndOfFile.QuadPart, "got eof %#I64x\n", std_info.EndOfFile.QuadPart ); + todo_wine ok( !std_info.AllocationSize.QuadPart, "got size %#I64x\n", std_info.AllocationSize.QuadPart ); + todo_wine ok( !std_info.EndOfFile.QuadPart, "got eof %#I64x\n", std_info.EndOfFile.QuadPart ); ok( std_info.NumberOfLinks == 2, "got %lu links\n", std_info.NumberOfLinks ); ok( !std_info.Directory, "got directory %u\n", std_info.Directory ); status = NtQueryInformationFile( handle, &io, &internal_info, sizeof(internal_info), FileInternalInformation ); ok( !status, "got %#lx\n", status ); status = NtQueryInformationFile( handle2, &io, &internal_info2, sizeof(internal_info2), FileInternalInformation ); ok( !status, "got %#lx\n", status ); - ok( internal_info.IndexNumber.QuadPart == internal_info2.IndexNumber.QuadPart, "got ids %#I64x vs %#I64x\n", + todo_wine ok( internal_info.IndexNumber.QuadPart == internal_info2.IndexNumber.QuadPart, "got ids %#I64x vs %#I64x\n", internal_info.IndexNumber.QuadPart, internal_info2.IndexNumber.QuadPart ); CloseHandle( handle2 );
@@ -6925,11 +6928,20 @@ static void test_reparse_points(void)
handle2 = CreateFileW( path, GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0 ); - ok( handle2 == INVALID_HANDLE_VALUE, "expected failure\n" ); - ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() ); + todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "expected failure\n" ); + todo_wine ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %lu\n", GetLastError() ); + if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 );
ret = MoveFileW( path2, path ); - ok( ret == TRUE, "got error %lu\n", GetLastError() ); + todo_wine ok( ret == TRUE, "got error %lu\n", GetLastError() ); + if (!ret) + { + /* undo what we incorrectly did above */ + WCHAR target[MAX_PATH]; + swprintf( target, ARRAY_SIZE(target), L"%stestreparse_file", temp_path ); + ret = MoveFileW( path2, target ); + ok( ret == TRUE, "got error %lu\n", GetLastError() ); + }
handle2 = CreateFileW( path2, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, 0 ); ok( handle2 != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); @@ -6950,15 +6962,15 @@ static void test_reparse_points(void) ok( ret == TRUE, "got error %lu\n", GetLastError() );
ret = GetFileAttributesW( path ); - ok( ret == (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_REPARSE_POINT), + todo_wine ok( ret == (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_REPARSE_POINT), "got attributes %#x\n", ret );
ret = GetFileAttributesW( path2 ); - ok( ret == FILE_ATTRIBUTE_ARCHIVE, "got attributes %#x\n", ret ); + todo_wine ok( ret == FILE_ATTRIBUTE_ARCHIVE, "got attributes %#x\n", ret );
status = NtQueryAttributesFile( &attr, &basic_info ); - ok( !status, "got %#lx\n", status ); - ok( basic_info.FileAttributes == (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_REPARSE_POINT), + todo_wine ok( !status, "got %#lx\n", status ); + todo_wine ok( basic_info.FileAttributes == (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_REPARSE_POINT), "got attributes %#lx\n", basic_info.FileAttributes );
/* Path names. */ @@ -6972,8 +6984,9 @@ static void test_reparse_points(void) /* ReOpenFile(). */
handle2 = ReOpenFile( handle, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0 ); - ok( handle2 == INVALID_HANDLE_VALUE, "expected failure\n" ); - ok( GetLastError() == ERROR_INVALID_REPARSE_DATA, "got error %lu\n", GetLastError() ); + todo_wine ok( handle2 == INVALID_HANDLE_VALUE, "expected failure\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_REPARSE_DATA, "got error %lu\n", GetLastError() ); + if (handle2 != INVALID_HANDLE_VALUE) CloseHandle( handle2 ); handle2 = ReOpenFile( handle, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_FLAG_OPEN_REPARSE_POINT ); ok( handle2 != INVALID_HANDLE_VALUE, "got error %lu\n", GetLastError() ); CloseHandle( handle2 ); @@ -7042,7 +7055,7 @@ static void test_reparse_points(void)
RtlInitUnicodeString( &nameW, L"testreparse_dirlink\file" ); status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( !status, "got %#lx\n", status ); + todo_wine ok( !status, "got %#lx\n", status ); NtClose( handle2 );
data_size = init_reparse_symlink( &data, L".\testreparse_dir\..\.\testreparse_dir2\.", SYMLINK_FLAG_RELATIVE ); @@ -7052,13 +7065,13 @@ static void test_reparse_points(void) RtlInitUnicodeString( &nameW, L"testreparse_dirlink" ); status = NtCreateFile( &handle2, GENERIC_ALL, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0 ); - ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status );
status = NtCreateFile( &handle2, GENERIC_ALL, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF, FILE_DIRECTORY_FILE, NULL, 0 ); - ok( !status, "got %#lx\n", status ); + todo_wine ok( !status, "got %#lx\n", status ); status = NtSetInformationFile( handle2, &io, &fdi, sizeof(fdi), FileDispositionInformation ); - ok( !status, "got %#lx\n", status ); + todo_wine ok( !status, "got %#lx\n", status ); NtClose( handle2 );
data_size = init_reparse_symlink( &data, L"./testreparse_dir", SYMLINK_FLAG_RELATIVE ); @@ -7080,11 +7093,11 @@ static void test_reparse_points(void) ok( !status, "got %#lx\n", status );
status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#lx\n", status );
data_size = init_reparse_symlink( &data, L"", SYMLINK_FLAG_RELATIVE ); status = NtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_SET_REPARSE_POINT, data, data_size, NULL, 0 ); - ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status );
data_size = init_reparse_symlink( &data, L"..", SYMLINK_FLAG_RELATIVE ); status = NtFsControlFile( handle, NULL, NULL, NULL, &io, FSCTL_SET_REPARSE_POINT, data, data_size, NULL, 0 ); @@ -7092,7 +7105,7 @@ static void test_reparse_points(void)
RtlInitUnicodeString( &nameW, L"testreparse_dirlink\" ); status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( !status, "got %#lx\n", status ); + todo_wine ok( !status, "got %#lx\n", status ); NtClose( handle2 );
/* Try to unwind past the drive root. */ @@ -7102,7 +7115,7 @@ static void test_reparse_points(void)
RtlInitUnicodeString( &nameW, L"testreparse_dirlink\" ); status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_IO_REPARSE_DATA_INVALID, "got %#lx\n", status );
/* Create an absolute symlink. */
@@ -7153,7 +7166,7 @@ static void test_reparse_points(void) ok( !status, "got %#lx\n", status );
status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status );
swprintf( path, ARRAY_SIZE(path), L".\testreparse_dir2", temp_path ); data_size = init_reparse_symlink( &data, path, 0 ); @@ -7161,7 +7174,7 @@ static void test_reparse_points(void) ok( !status, "got %#lx\n", status );
status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_NAME_INVALID, "got %#lx\n", status );
swprintf( path, ARRAY_SIZE(path), L"\??\%s.\testreparse_dir2", temp_path ); data_size = init_reparse_symlink( &data, path, 0 ); @@ -7169,7 +7182,7 @@ static void test_reparse_points(void) ok( !status, "got %#lx\n", status );
status = NtOpenFile( &handle2, READ_CONTROL, &attr, &io, 0, 0 ); - ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "got %#lx\n", status ); + todo_wine ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "got %#lx\n", status );
swprintf( path, ARRAY_SIZE(path), L"\??\%stestreparse_dir2\..\testreparse_dir2", temp_path ); data_size = init_reparse_symlink( &data, path, 0 ); diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 3c59f2c63e9..01e9c1bb9ed 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -3972,6 +3972,58 @@ static NTSTATUS resolve_reparse_point( int fd, int root_fd, OBJECT_ATTRIBUTES *a
switch (data->ReparseTag) { + case IO_REPARSE_TAG_SYMLINK: + { + const WCHAR *target = data->SymbolicLinkReparseBuffer.PathBuffer + + data->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR); + USHORT target_len = data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + + if (data->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) + { + WCHAR *new_nt_name; + + TRACE( "target %s\n", debugstr_wn(target, target_len) ); + + if (!target_len) + { + free( data ); + return STATUS_IO_REPARSE_DATA_INVALID; + } + + if (!(new_nt_name = malloc( (nt_pos + target_len + 1 + remainder_len + 1) * sizeof(WCHAR) ))) + { + free( data ); + return STATUS_NO_MEMORY; + } + + memcpy( new_nt_name, name, nt_pos * sizeof(WCHAR) ); + memcpy( new_nt_name + nt_pos, target, target_len * sizeof(WCHAR) ); + if (remainder_len) + { + if (target[target_len - 1] != '\') + new_nt_name[nt_pos + target_len++] = '\'; + memcpy( new_nt_name + nt_pos + target_len, remainder, remainder_len * sizeof(WCHAR) ); + } + new_nt_name[nt_pos + target_len + remainder_len] = 0; + + free( nt_name->Buffer ); + nt_name->Buffer = new_nt_name; + nt_name->Length = (nt_pos + target_len + remainder_len) * sizeof(WCHAR); + nt_name->MaximumLength = nt_name->Length + sizeof(WCHAR); + attr->ObjectName = nt_name; + + status = lookup_unix_name( root_fd, attr, nt_name, nt_pos, unix_name, unix_len, pos, + disposition, open_reparse, is_unix, reparse_count ); + } + else + { + status = resolve_absolute_reparse_point( target, target_len, attr, nt_name, + remainder, remainder_len, unix_name, + disposition, open_reparse, reparse_count ); + } + break; + } + case IO_REPARSE_TAG_MOUNT_POINT: { const WCHAR *target = data->MountPointReparseBuffer.PathBuffer
This merge request was approved by Elizabeth Figura.