mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Rebase against 5ccc463a4e3ba181b96a161c3c8cd4bc0cb0e607.
This commit is contained in:
parent
1dc5f2f601
commit
f3b30373fb
@ -152,7 +152,7 @@ for more details.*
|
||||
* Fix handling of ANSI NTLM credentials ([Wine Bug #37063](https://bugs.winehq.org/show_bug.cgi?id=37063))
|
||||
* Fix handling of empty section and key name for profile files. ([Wine Bug #8036](https://bugs.winehq.org/show_bug.cgi?id=8036))
|
||||
* Fix handling of invert_y in DrawTextExW ([Wine Bug #22109](https://bugs.winehq.org/show_bug.cgi?id=22109))
|
||||
* Fix handling of opening a file with RootDirectory pointing to a file handle
|
||||
* ~~Fix handling of opening a file with RootDirectory pointing to a file handle~~
|
||||
* Fix handling of opening read-only files for FILE_DELETE_ON_CLOSE ([Wine Bug #38417](https://bugs.winehq.org/show_bug.cgi?id=38417))
|
||||
* Fix handling of window attributes for WS_EX_LAYERED | WS_EX_COMPOSITED ([Wine Bug #37876](https://bugs.winehq.org/show_bug.cgi?id=37876))
|
||||
* Fix issues with dragging layers between images in Adobe Photoshop 7.0 ([Wine Bug #12007](https://bugs.winehq.org/show_bug.cgi?id=12007))
|
||||
@ -263,7 +263,7 @@ for more details.*
|
||||
* Support for NVIDIA video encoder library (nvencodeapi)
|
||||
* Support for NtQuerySection ([Wine Bug #37338](https://bugs.winehq.org/show_bug.cgi?id=37338))
|
||||
* ~~Support for NtSetInformationFile class FileDispositionInformation~~ ([Wine Bug #30397](https://bugs.winehq.org/show_bug.cgi?id=30397))
|
||||
* Support for NtSetInformationFile class FileLinkInformation
|
||||
* ~~Support for NtSetInformationFile class FileLinkInformation~~
|
||||
* ~~Support for NtSetInformationFile class FileRenameInformation~~ ([Wine Bug #30399](https://bugs.winehq.org/show_bug.cgi?id=30399))
|
||||
* Support for PulseAudio backend for audio ([Wine Bug #10495](https://bugs.winehq.org/show_bug.cgi?id=10495))
|
||||
* Support for SHCreateSessionKey ([Wine Bug #35630](https://bugs.winehq.org/show_bug.cgi?id=35630))
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 4c33b67050e2dc88ab8f1e08f4b2559132a50262 Mon Sep 17 00:00:00 2001
|
||||
From b4eabfd0a1eaca783c6a0fe35de8b1166412f078 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 3 Jun 2015 01:37:34 +0200
|
||||
Subject: server: When combining root and name, make sure there is only one
|
||||
@ -12,10 +12,10 @@ Changes in v2:
|
||||
2 files changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 99aaa37..d1055e8 100644
|
||||
index 440cfaa..40c932b 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -2068,8 +2068,8 @@ static void test_file_rename_information(void)
|
||||
@@ -2111,8 +2111,8 @@ static void test_file_rename_information(void)
|
||||
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
@ -27,18 +27,18 @@ index 99aaa37..d1055e8 100644
|
||||
|
||||
CloseHandle( handle );
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index 04891e7..c0b5548 100644
|
||||
index b30ae11..07e0fc5 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1720,6 +1720,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
|
||||
static char *dup_fd_name( struct fd *root, const char *name )
|
||||
char *dup_fd_name( struct fd *root, const char *name )
|
||||
{
|
||||
char *ret;
|
||||
+ int len;
|
||||
|
||||
if (!root) return strdup( name );
|
||||
if (!root->unix_name) return NULL;
|
||||
@@ -1727,11 +1728,18 @@ static char *dup_fd_name( struct fd *root, const char *name )
|
||||
@@ -1727,11 +1728,18 @@ char *dup_fd_name( struct fd *root, const char *name )
|
||||
/* skip . prefix */
|
||||
if (name[0] == '.' && (!name[1] || name[1] == '/')) name++;
|
||||
|
||||
|
@ -1,730 +0,0 @@
|
||||
From 3a74e4ad232bb6c15925d15225c0ec039143177b Mon Sep 17 00:00:00 2001
|
||||
From: Qian Hong <qhong@codeweavers.com>
|
||||
Date: Wed, 3 Jun 2015 17:41:59 +0800
|
||||
Subject: ntdll/tests: Add tests for FileLinkInformation class.
|
||||
|
||||
Mostly copy and paste from Sebastian Lackner's FileNameInformation class
|
||||
tests, credit to Sebastian.
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 698 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 698 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index d1055e8..177c2c5 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -2079,6 +2079,703 @@ static void test_file_rename_information(void)
|
||||
delete_object( newpath );
|
||||
}
|
||||
|
||||
+static void test_file_link_information(void)
|
||||
+{
|
||||
+ static const WCHAR foo_txtW[] = {'\\','f','o','o','.','t','x','t',0};
|
||||
+ static const WCHAR fooW[] = {'f','o','o',0};
|
||||
+ WCHAR tmp_path[MAX_PATH], oldpath[MAX_PATH + 16], newpath[MAX_PATH + 16], *filename, *p;
|
||||
+ FILE_LINK_INFORMATION *fli;
|
||||
+ FILE_NAME_INFORMATION *fni;
|
||||
+ BOOL success, fileDeleted;
|
||||
+ UNICODE_STRING name_str;
|
||||
+ HANDLE handle, handle2;
|
||||
+ IO_STATUS_BLOCK io;
|
||||
+ NTSTATUS res;
|
||||
+
|
||||
+ GetTempPathW( MAX_PATH, tmp_path );
|
||||
+
|
||||
+ /* oldpath is a file, newpath doesn't exist */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ DeleteFileW( newpath );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ todo_wine ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
|
||||
+ res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
+ ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
|
||||
+ wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
+ HeapFree( GetProcessHeap(), 0, fni );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = FALSE, target file opened */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened with FILE_SHARE_DELETE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a file, ReplaceIfExists = TRUE, target file opened with FILE_SHARE_DELETE | FILE_SHARE_WRITE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, FILE_SHARE_DELETE | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath doesn't exist, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ DeleteFileW( newpath );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( fileDeleted, "file should not exist\n" );
|
||||
+
|
||||
+ fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
|
||||
+ res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
+ ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
|
||||
+ wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
+ HeapFree( GetProcessHeap(), 0, fni );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory (but child object opened), newpath doesn't exist, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ lstrcpyW( newpath, oldpath );
|
||||
+ lstrcatW( newpath, foo_txtW );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ DeleteFileW( newpath );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( fileDeleted, "file should not exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a file, ReplaceIfExists = FALSE, target file opened */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a file, ReplaceIfExists = TRUE, target file opened */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a directory, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ success = CreateDirectoryW( newpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ success = CreateDirectoryW( newpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a directory, newpath is a directory, ReplaceIfExists = TRUE, target file opened */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( oldpath );
|
||||
+ success = CreateDirectoryW( oldpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ success = CreateDirectoryW( newpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ handle2 = CreateFileW( newpath, GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a directory, ReplaceIfExists = FALSE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ success = CreateDirectoryW( newpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath is a directory, ReplaceIfExists = TRUE */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ success = CreateDirectoryW( newpath, NULL );
|
||||
+ ok( success != 0, "failed to create temp directory\n" );
|
||||
+ pRtlDosPathNameToNtPathName_U( newpath, &name_str, NULL, NULL );
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + name_str.Length );
|
||||
+ fli->ReplaceIfExists = TRUE;
|
||||
+ fli->RootDirectory = NULL;
|
||||
+ fli->FileNameLength = name_str.Length;
|
||||
+ memcpy( fli->FileName, name_str.Buffer, name_str.Length );
|
||||
+ pRtlFreeUnicodeString( &name_str );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+
|
||||
+ /* oldpath is a file, newpath doesn't exist, test with RootDirectory != NULL */
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, oldpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ handle = CreateFileW( oldpath, GENERIC_WRITE | DELETE, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( handle != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ res = GetTempFileNameW( tmp_path, fooW, 0, newpath );
|
||||
+ ok( res != 0, "failed to create temp file\n" );
|
||||
+ DeleteFileW( newpath );
|
||||
+ for (filename = newpath, p = newpath; *p; p++)
|
||||
+ if (*p == '\\') filename = p + 1;
|
||||
+ handle2 = CreateFileW( tmp_path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0 );
|
||||
+ ok( handle2 != INVALID_HANDLE_VALUE, "CreateFileW failed\n" );
|
||||
+
|
||||
+ fli = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_LINK_INFORMATION) + lstrlenW(filename) * sizeof(WCHAR) );
|
||||
+ fli->ReplaceIfExists = FALSE;
|
||||
+ fli->RootDirectory = handle2;
|
||||
+ fli->FileNameLength = lstrlenW(filename) * sizeof(WCHAR);
|
||||
+ memcpy( fli->FileName, filename, fli->FileNameLength );
|
||||
+
|
||||
+ U(io).Status = 0xdeadbeef;
|
||||
+ res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
+ todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
+ fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
+ todo_wine ok( !fileDeleted, "file should exist\n" );
|
||||
+
|
||||
+ fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
|
||||
+ res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
+ ok( !lstrcmpW(fni->FileName, oldpath + 2), "FileName expected %s, got %s\n",
|
||||
+ wine_dbgstr_w(oldpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
+ HeapFree( GetProcessHeap(), 0, fni );
|
||||
+
|
||||
+ CloseHandle( handle );
|
||||
+ CloseHandle( handle2 );
|
||||
+ HeapFree( GetProcessHeap(), 0, fli );
|
||||
+ delete_object( oldpath );
|
||||
+ delete_object( newpath );
|
||||
+}
|
||||
+
|
||||
static void test_file_both_information(void)
|
||||
{
|
||||
IO_STATUS_BLOCK io;
|
||||
@@ -3570,6 +4267,7 @@ START_TEST(file)
|
||||
test_file_full_size_information();
|
||||
test_file_all_name_information();
|
||||
test_file_rename_information();
|
||||
+ test_file_link_information();
|
||||
test_file_disposition_information();
|
||||
test_query_volume_information_file();
|
||||
test_query_attribute_information_file();
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,344 +0,0 @@
|
||||
From 33b20afef41c75ec5fb2407ec226daef12039c97 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Wed, 3 Jun 2015 17:04:23 +0200
|
||||
Subject: server: Implement support for FileLinkInformation class in
|
||||
NtSetInformationFile.
|
||||
|
||||
---
|
||||
dlls/ntdll/file.c | 44 ++++++++++++++++++++++++++++++++++++++++
|
||||
dlls/ntdll/tests/file.c | 54 ++++++++++++++++++++++++-------------------------
|
||||
server/fd.c | 25 +++++++++++++++++++----
|
||||
server/protocol.def | 1 +
|
||||
4 files changed, 93 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
|
||||
index 3cef11b..be6b591 100644
|
||||
--- a/dlls/ntdll/file.c
|
||||
+++ b/dlls/ntdll/file.c
|
||||
@@ -2813,6 +2813,50 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||
+ req->link = FALSE;
|
||||
+ wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
|
||||
+ io->u.Status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+
|
||||
+ RtlFreeAnsiString( &unix_name );
|
||||
+ }
|
||||
+ else io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
+ break;
|
||||
+
|
||||
+ case FileLinkInformation:
|
||||
+ if (len >= sizeof(FILE_LINK_INFORMATION))
|
||||
+ {
|
||||
+ FILE_LINK_INFORMATION *info = ptr;
|
||||
+ UNICODE_STRING name_str;
|
||||
+ OBJECT_ATTRIBUTES attr;
|
||||
+ ANSI_STRING unix_name;
|
||||
+
|
||||
+ name_str.Buffer = info->FileName;
|
||||
+ name_str.Length = info->FileNameLength;
|
||||
+ name_str.MaximumLength = info->FileNameLength + sizeof(WCHAR);
|
||||
+
|
||||
+ attr.Length = sizeof(attr);
|
||||
+ attr.ObjectName = &name_str;
|
||||
+ attr.RootDirectory = info->RootDirectory;
|
||||
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
|
||||
+
|
||||
+ io->u.Status = nt_to_unix_file_name_attr( &attr, &unix_name, FILE_OPEN_IF );
|
||||
+ if (io->u.Status != STATUS_SUCCESS && io->u.Status != STATUS_NO_SUCH_FILE)
|
||||
+ break;
|
||||
+
|
||||
+ if (!info->ReplaceIfExists && io->u.Status == STATUS_SUCCESS)
|
||||
+ {
|
||||
+ RtlFreeAnsiString( &unix_name );
|
||||
+ io->u.Status = STATUS_OBJECT_NAME_COLLISION;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SERVER_START_REQ( set_fd_name_info )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( handle );
|
||||
+ req->rootdir = wine_server_obj_handle( attr.RootDirectory );
|
||||
+ req->link = TRUE;
|
||||
wine_server_add_data( req, unix_name.Buffer, unix_name.Length );
|
||||
io->u.Status = wine_server_call( req );
|
||||
}
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 177c2c5..5b3db09 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -2113,12 +2113,12 @@ static void test_file_link_information(void)
|
||||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
- todo_wine ok( !fileDeleted, "file should exist\n" );
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
|
||||
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
|
||||
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
@@ -2152,7 +2152,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2185,7 +2185,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2215,8 +2215,8 @@ static void test_file_link_information(void)
|
||||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2249,7 +2249,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2283,7 +2283,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2317,7 +2317,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2352,7 +2352,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef , "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2399,7 +2399,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2433,8 +2433,8 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2470,8 +2470,8 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2505,7 +2505,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2541,7 +2541,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2578,8 +2578,8 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
- "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION || res == STATUS_FILE_IS_A_DIRECTORY /* > Win XP */,
|
||||
+ "res expected STATUS_OBJECT_NAME_COLLISION or STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2615,7 +2615,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2654,7 +2654,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
+ ok( res == STATUS_FILE_IS_A_DIRECTORY, "res expected STATUS_FILE_IS_A_DIRECTORY, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2688,7 +2688,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
+ ok( res == STATUS_OBJECT_NAME_COLLISION, "res expected STATUS_OBJECT_NAME_COLLISION, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2721,7 +2721,7 @@ static void test_file_link_information(void)
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
todo_wine ok( U(io).Status == 0xdeadbeef, "io.Status expected 0xdeadbeef, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
+ ok( res == STATUS_ACCESS_DENIED, "res expected STATUS_ACCESS_DENIED, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
@@ -2754,12 +2754,12 @@ static void test_file_link_information(void)
|
||||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fli, sizeof(FILE_LINK_INFORMATION) + fli->FileNameLength, FileLinkInformation );
|
||||
- todo_wine ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
- todo_wine ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
+ ok( U(io).Status == STATUS_SUCCESS, "io.Status expected STATUS_SUCCESS, got %x\n", U(io).Status );
|
||||
+ ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fileDeleted = GetFileAttributesW( oldpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
- todo_wine ok( !fileDeleted, "file should exist\n" );
|
||||
+ ok( !fileDeleted, "file should exist\n" );
|
||||
|
||||
fni = HeapAlloc( GetProcessHeap(), 0, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR) );
|
||||
res = pNtQueryInformationFile( handle, &io, fni, sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR), FileNameInformation );
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index c0b5548..94489e7 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -2275,7 +2275,7 @@ static void set_fd_disposition( struct fd *fd, int unlink )
|
||||
}
|
||||
|
||||
/* set new name for the fd */
|
||||
-static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len )
|
||||
+static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len, int do_link )
|
||||
{
|
||||
struct inode *inode;
|
||||
struct stat st;
|
||||
@@ -2307,6 +2307,14 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
|
||||
name = combined_name;
|
||||
}
|
||||
|
||||
+ /* when creating a hard link, source must be a file */
|
||||
+ if (do_link && fd->unix_fd != -1 &&
|
||||
+ !fstat( fd->unix_fd, &st ) && S_ISDIR( st.st_mode ))
|
||||
+ {
|
||||
+ set_error( STATUS_FILE_IS_A_DIRECTORY );
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
if (!stat( name, &st ))
|
||||
{
|
||||
/* can't replace directories or special files */
|
||||
@@ -2328,15 +2336,24 @@ static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, da
|
||||
}
|
||||
}
|
||||
|
||||
+ /* link() expects that the target doesn't exist */
|
||||
/* rename() cannot replace files with directories */
|
||||
- if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
|
||||
- S_ISDIR( st.st_mode ) && unlink( name ))
|
||||
+ if ((do_link || (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
|
||||
+ S_ISDIR( st.st_mode ))) && unlink( name ))
|
||||
{
|
||||
file_set_error();
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
+ if (do_link)
|
||||
+ {
|
||||
+ if (link( fd->unix_name, name ))
|
||||
+ file_set_error();
|
||||
+ free( name );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (rename( fd->unix_name, name ))
|
||||
{
|
||||
file_set_error();
|
||||
@@ -2576,7 +2593,7 @@ DECL_HANDLER(set_fd_name_info)
|
||||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
- set_fd_name( fd, root_fd, get_req_data(), get_req_data_size() );
|
||||
+ set_fd_name( fd, root_fd, get_req_data(), get_req_data_size(), req->link );
|
||||
release_object( fd );
|
||||
}
|
||||
if (root_fd) release_object( root_fd );
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index d3ff4b7..c313006 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3536,6 +3536,7 @@ enum coords_relative
|
||||
@REQ(set_fd_name_info)
|
||||
obj_handle_t handle; /* handle to a file or directory */
|
||||
obj_handle_t rootdir; /* root directory */
|
||||
+ int link; /* link instead of renaming */
|
||||
VARARG(filename,string); /* new file name */
|
||||
@END
|
||||
|
||||
--
|
||||
2.5.0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Fixes: [30397] Support for NtSetInformationFile class FileDispositionInformation
|
||||
# Fixes: [30399] Support for NtSetInformationFile class FileRenameInformation
|
||||
Fixes: Support for NtSetInformationFile class FileLinkInformation
|
||||
# Fixes: Support for NtSetInformationFile class FileLinkInformation
|
||||
Depends: server-File_Permissions
|
||||
|
@ -55,7 +55,7 @@ version()
|
||||
echo "Copyright (C) 2014-2015 the Wine Staging project authors."
|
||||
echo ""
|
||||
echo "Patchset to be applied on upstream Wine:"
|
||||
echo " commit 5021e91940fe01a54e6ee91f9d9f246ce8f6dd84"
|
||||
echo " commit 5ccc463a4e3ba181b96a161c3c8cd4bc0cb0e607"
|
||||
echo ""
|
||||
}
|
||||
|
||||
@ -215,7 +215,6 @@ patch_enable_all ()
|
||||
enable_server_PeekMessage="$1"
|
||||
enable_server_Pipe_ObjectName="$1"
|
||||
enable_server_Realtime_Priority="$1"
|
||||
enable_server_RootDirectory_File="$1"
|
||||
enable_server_Shared_Memory="$1"
|
||||
enable_server_Stored_ACLs="$1"
|
||||
enable_server_Timestamp_Compat="$1"
|
||||
@ -731,9 +730,6 @@ patch_enable ()
|
||||
server-Realtime_Priority)
|
||||
enable_server_Realtime_Priority="$2"
|
||||
;;
|
||||
server-RootDirectory_File)
|
||||
enable_server_RootDirectory_File="$2"
|
||||
;;
|
||||
server-Shared_Memory)
|
||||
enable_server_Shared_Memory="$2"
|
||||
;;
|
||||
@ -1714,19 +1710,8 @@ if test "$enable_server_Stored_ACLs" -eq 1; then
|
||||
if test "$enable_server_File_Permissions" -gt 1; then
|
||||
abort "Patchset server-File_Permissions disabled, but server-Stored_ACLs depends on that."
|
||||
fi
|
||||
if test "$enable_server_RootDirectory_File" -gt 1; then
|
||||
abort "Patchset server-RootDirectory_File disabled, but server-Stored_ACLs depends on that."
|
||||
fi
|
||||
enable_ntdll_DOS_Attributes=1
|
||||
enable_server_File_Permissions=1
|
||||
enable_server_RootDirectory_File=1
|
||||
fi
|
||||
|
||||
if test "$enable_server_RootDirectory_File" -eq 1; then
|
||||
if test "$enable_ntdll_FileDispositionInformation" -gt 1; then
|
||||
abort "Patchset ntdll-FileDispositionInformation disabled, but server-RootDirectory_File depends on that."
|
||||
fi
|
||||
enable_ntdll_FileDispositionInformation=1
|
||||
fi
|
||||
|
||||
if test "$enable_nvencodeapi_Video_Encoder" -eq 1; then
|
||||
@ -3154,20 +3139,16 @@ fi
|
||||
# | * server-File_Permissions
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/file.c, dlls/ntdll/tests/file.c, server/fd.c, server/protocol.def
|
||||
# | * dlls/ntdll/tests/file.c, server/fd.c
|
||||
# |
|
||||
if test "$enable_ntdll_FileDispositionInformation" -eq 1; then
|
||||
patch_apply ntdll-FileDispositionInformation/0001-ntdll-tests-Added-tests-to-set-disposition-on-file-w.patch
|
||||
patch_apply ntdll-FileDispositionInformation/0002-server-Do-not-allow-to-set-disposition-on-file-which.patch
|
||||
patch_apply ntdll-FileDispositionInformation/0003-server-When-combining-root-and-name-make-sure-there-.patch
|
||||
patch_apply ntdll-FileDispositionInformation/0004-ntdll-tests-Add-tests-for-FileLinkInformation-class.patch
|
||||
patch_apply ntdll-FileDispositionInformation/0005-server-Implement-support-for-FileLinkInformation-cla.patch
|
||||
(
|
||||
echo '+ { "Qian Hong", "ntdll/tests: Added tests to set disposition on file which is mapped to memory.", 1 },';
|
||||
echo '+ { "Qian Hong", "server: Do not allow to set disposition on file which has a file mapping.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: When combining root and name, make sure there is only one slash.", 2 },';
|
||||
echo '+ { "Qian Hong", "ntdll/tests: Add tests for FileLinkInformation class.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "server: Implement support for FileLinkInformation class in NtSetInformationFile.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
@ -4361,25 +4342,10 @@ if test "$enable_server_Delete_On_Close" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset server-RootDirectory_File
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * server-File_Permissions, ntdll-FileDispositionInformation
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/ntdll/tests/file.c, server/fd.c, server/file.c, server/file.h
|
||||
# |
|
||||
if test "$enable_server_RootDirectory_File" -eq 1; then
|
||||
patch_apply server-RootDirectory_File/0001-server-Fix-handling-of-opening-a-file-with-RootDirec.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "server: Fix handling of opening a file with RootDirectory pointing to a file handle.", 3 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset server-Stored_ACLs
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions, ntdll-FileDispositionInformation, server-RootDirectory_File
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#33576] Support for stored file ACLs
|
||||
@ -4410,8 +4376,7 @@ fi
|
||||
# Patchset server-Inherited_ACLs
|
||||
# |
|
||||
# | This patchset has the following (direct or indirect) dependencies:
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions, ntdll-FileDispositionInformation, server-RootDirectory_File, server-
|
||||
# | Stored_ACLs
|
||||
# | * ntdll-DOS_Attributes, server-File_Permissions, server-Stored_ACLs
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/advapi32/tests/security.c, server/file.c
|
||||
|
@ -1,228 +0,0 @@
|
||||
From 7b50d145c867f5724e20120cd54995752279291a Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Fri, 29 May 2015 22:49:24 +0200
|
||||
Subject: server: Fix handling of opening a file with RootDirectory pointing to
|
||||
a file handle. (v3)
|
||||
|
||||
Changes in v2:
|
||||
* Seek back to the beginning of file in duplicated file descriptor.
|
||||
---
|
||||
dlls/ntdll/tests/file.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
|
||||
server/fd.c | 34 +++++++++++++++++++++++++++-------
|
||||
server/file.c | 23 ++++++++++++++++++++++-
|
||||
server/file.h | 1 +
|
||||
4 files changed, 96 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
|
||||
index 1f009f6..fbf9daf 100644
|
||||
--- a/dlls/ntdll/tests/file.c
|
||||
+++ b/dlls/ntdll/tests/file.c
|
||||
@@ -297,7 +297,8 @@ static void create_file_test(void)
|
||||
|
||||
static void open_file_test(void)
|
||||
{
|
||||
- static const WCHAR fooW[] = {'f','o','o',0};
|
||||
+ static const char testdata[] = "Hello World";
|
||||
+ static WCHAR fooW[] = {'f','o','o',0};
|
||||
NTSTATUS status;
|
||||
HANDLE dir, root, handle, file;
|
||||
WCHAR path[MAX_PATH], tmpfile[MAX_PATH];
|
||||
@@ -306,7 +307,8 @@ static void open_file_test(void)
|
||||
IO_STATUS_BLOCK io;
|
||||
UNICODE_STRING nameW;
|
||||
UINT i, len;
|
||||
- BOOL restart = TRUE;
|
||||
+ BOOL ret, restart = TRUE;
|
||||
+ DWORD numbytes;
|
||||
|
||||
len = GetWindowsDirectoryW( path, MAX_PATH );
|
||||
pRtlDosPathNameToNtPathName_U( path, &nameW, NULL, NULL );
|
||||
@@ -432,6 +434,14 @@ static void open_file_test(void)
|
||||
GetTempFileNameW( path, fooW, 0, tmpfile );
|
||||
pRtlDosPathNameToNtPathName_U( tmpfile, &nameW, NULL, NULL );
|
||||
|
||||
+ file = CreateFileW( tmpfile, FILE_WRITE_DATA, 0, NULL, CREATE_ALWAYS, 0, 0 );
|
||||
+ ok( file != INVALID_HANDLE_VALUE, "CreateFile error %d\n", GetLastError() );
|
||||
+ numbytes = 0xdeadbeef;
|
||||
+ ret = WriteFile( file, testdata, sizeof(testdata) - 1, &numbytes, NULL );
|
||||
+ ok( ret, "WriteFile failed with error %u\n", GetLastError() );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "failed to write all data\n" );
|
||||
+ CloseHandle( file );
|
||||
+
|
||||
attr.Length = sizeof(attr);
|
||||
attr.RootDirectory = 0;
|
||||
attr.ObjectName = &nameW;
|
||||
@@ -443,13 +453,46 @@ static void open_file_test(void)
|
||||
ok( !status, "open %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );
|
||||
pRtlFreeUnicodeString( &nameW );
|
||||
|
||||
+ numbytes = 0xdeadbeef;
|
||||
+ memset( data, 0, sizeof(data) );
|
||||
+ ret = ReadFile( file, data, sizeof(data), &numbytes, NULL );
|
||||
+ ok( ret, "ReadFile failed with error %u\n", GetLastError() );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
|
||||
+ ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
|
||||
+
|
||||
+ nameW.Length = sizeof(fooW) - sizeof(WCHAR);
|
||||
+ nameW.Buffer = fooW;
|
||||
+ attr.RootDirectory = file;
|
||||
+ attr.ObjectName = &nameW;
|
||||
+ status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
|
||||
+ FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
+ ok( status == STATUS_OBJECT_PATH_NOT_FOUND,
|
||||
+ "expected STATUS_OBJECT_PATH_NOT_FOUND, got %08x\n", status );
|
||||
+
|
||||
nameW.Length = 0;
|
||||
nameW.Buffer = NULL;
|
||||
attr.RootDirectory = file;
|
||||
attr.ObjectName = &nameW;
|
||||
status = pNtOpenFile( &root, SYNCHRONIZE|FILE_LIST_DIRECTORY, &attr, &io,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT );
|
||||
- todo_wine ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
|
||||
+ ok( !status, "open %s failed %x\n", wine_dbgstr_w(tmpfile), status );
|
||||
+
|
||||
+ numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
|
||||
+ numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
|
||||
+ ok( numbytes == 0, "SetFilePointer returned %u\n", numbytes );
|
||||
+
|
||||
+ numbytes = 0xdeadbeef;
|
||||
+ memset( data, 0, sizeof(data) );
|
||||
+ ret = ReadFile( root, data, sizeof(data), &numbytes, NULL );
|
||||
+ ok( ret, "ReadFile failed with error %u\n", GetLastError() );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "failed to read all data\n" );
|
||||
+ ok( !memcmp( data, testdata, sizeof(testdata) - 1 ), "testdata doesn't match\n" );
|
||||
+
|
||||
+ numbytes = SetFilePointer( file, 0, 0, FILE_CURRENT );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
|
||||
+ numbytes = SetFilePointer( root, 0, 0, FILE_CURRENT );
|
||||
+ ok( numbytes == sizeof(testdata) - 1, "SetFilePointer returned %u\n", numbytes );
|
||||
|
||||
CloseHandle( file );
|
||||
CloseHandle( root );
|
||||
diff --git a/server/fd.c b/server/fd.c
|
||||
index ae97a94..04c0e42 100644
|
||||
--- a/server/fd.c
|
||||
+++ b/server/fd.c
|
||||
@@ -1718,7 +1718,7 @@ void set_fd_user( struct fd *fd, const struct fd_ops *user_ops, struct object *u
|
||||
fd->user = user;
|
||||
}
|
||||
|
||||
-static char *dup_fd_name( struct fd *root, const char *name )
|
||||
+char *dup_fd_name( struct fd *root, const char *name )
|
||||
{
|
||||
char *ret;
|
||||
int len;
|
||||
@@ -2325,14 +2325,36 @@ DECL_HANDLER(flush)
|
||||
DECL_HANDLER(open_file_object)
|
||||
{
|
||||
struct unicode_str name;
|
||||
- struct directory *root = NULL;
|
||||
+ struct directory *root;
|
||||
struct object *obj, *result;
|
||||
|
||||
get_req_unicode_str( &name );
|
||||
- if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
|
||||
- return;
|
||||
+ if (req->rootdir)
|
||||
+ {
|
||||
+ if ((root = get_directory_obj( current->process, req->rootdir, 0 )))
|
||||
+ {
|
||||
+ obj = open_object_dir( root, &name, req->attributes, NULL );
|
||||
+ release_object( root );
|
||||
+ }
|
||||
+ else if (get_error() == STATUS_OBJECT_TYPE_MISMATCH &&
|
||||
+ (obj = (struct object *)get_file_obj( current->process, req->rootdir, 0 )))
|
||||
+ {
|
||||
+ if (name.len)
|
||||
+ {
|
||||
+ release_object( obj );
|
||||
+ set_error( STATUS_OBJECT_PATH_NOT_FOUND );
|
||||
+ return;
|
||||
+ }
|
||||
+ clear_error();
|
||||
+ }
|
||||
+ else return;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ obj = open_object_dir( NULL, &name, req->attributes, NULL );
|
||||
+ }
|
||||
|
||||
- if ((obj = open_object_dir( root, &name, req->attributes, NULL )))
|
||||
+ if (obj)
|
||||
{
|
||||
if ((result = obj->ops->open_file( obj, req->access, req->sharing, req->options )))
|
||||
{
|
||||
@@ -2341,8 +2363,6 @@ DECL_HANDLER(open_file_object)
|
||||
}
|
||||
release_object( obj );
|
||||
}
|
||||
-
|
||||
- if (root) release_object( root );
|
||||
}
|
||||
|
||||
/* get the Unix name from a file handle */
|
||||
diff --git a/server/file.c b/server/file.c
|
||||
index b673bbc..56600d5 100644
|
||||
--- a/server/file.c
|
||||
+++ b/server/file.c
|
||||
@@ -67,6 +67,8 @@ static void file_dump( struct object *obj, int verbose );
|
||||
static struct fd *file_get_fd( struct object *obj );
|
||||
static struct security_descriptor *file_get_sd( struct object *obj );
|
||||
static int file_set_sd( struct object *obj, const struct security_descriptor *sd, unsigned int set_info );
|
||||
+static struct object *file_open_file( struct object *obj, unsigned int access,
|
||||
+ unsigned int sharing, unsigned int options );
|
||||
static void file_destroy( struct object *obj );
|
||||
|
||||
static int file_get_poll_events( struct fd *fd );
|
||||
@@ -88,7 +90,7 @@ static const struct object_ops file_ops =
|
||||
file_get_sd, /* get_sd */
|
||||
file_set_sd, /* set_sd */
|
||||
no_lookup_name, /* lookup_name */
|
||||
- no_open_file, /* open_file */
|
||||
+ file_open_file, /* open_file */
|
||||
fd_close_handle, /* close_handle */
|
||||
file_destroy /* destroy */
|
||||
};
|
||||
@@ -597,6 +599,25 @@ static int file_set_sd( struct object *obj, const struct security_descriptor *sd
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static struct object *file_open_file( struct object *obj, unsigned int access,
|
||||
+ unsigned int sharing, unsigned int options )
|
||||
+{
|
||||
+ struct file *file = (struct file *)obj;
|
||||
+ struct object *new_file = NULL;
|
||||
+ char *unix_name;
|
||||
+
|
||||
+ assert( obj->ops == &file_ops );
|
||||
+
|
||||
+ if ((unix_name = dup_fd_name( file->fd, "" )))
|
||||
+ {
|
||||
+ new_file = create_file( NULL, unix_name, strlen(unix_name), access,
|
||||
+ sharing, FILE_OPEN, options, 0, NULL );
|
||||
+ free( unix_name );
|
||||
+ }
|
||||
+ else set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
+ return new_file;
|
||||
+}
|
||||
+
|
||||
static void file_destroy( struct object *obj )
|
||||
{
|
||||
struct file *file = (struct file *)obj;
|
||||
diff --git a/server/file.h b/server/file.h
|
||||
index 460656f..47e6692 100644
|
||||
--- a/server/file.h
|
||||
+++ b/server/file.h
|
||||
@@ -82,6 +82,7 @@ extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
|
||||
extern void allow_fd_caching( struct fd *fd );
|
||||
extern void set_fd_signaled( struct fd *fd, int signaled );
|
||||
extern int is_fd_signaled( struct fd *fd );
|
||||
+extern char *dup_fd_name( struct fd *root, const char *name );
|
||||
|
||||
extern int default_fd_signaled( struct object *obj, struct wait_queue_entry *entry );
|
||||
extern unsigned int default_fd_map_access( struct object *obj, unsigned int access );
|
||||
--
|
||||
2.4.2
|
||||
|
@ -1,2 +0,0 @@
|
||||
Fixes: Fix handling of opening a file with RootDirectory pointing to a file handle
|
||||
Depends: ntdll-FileDispositionInformation
|
@ -1,4 +1,3 @@
|
||||
Depends: ntdll-DOS_Attributes
|
||||
Depends: server-File_Permissions
|
||||
Depends: server-RootDirectory_File
|
||||
Fixes: [33576] Support for stored file ACLs
|
||||
|
Loading…
Reference in New Issue
Block a user