ntdll: Implement FileRenameInformation support.
This commit is contained in:
parent
6899eade5d
commit
857d436784
|
@ -2770,7 +2770,7 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
{
|
||||
FILE_DISPOSITION_INFORMATION *info = ptr;
|
||||
|
||||
SERVER_START_REQ( set_fd_info )
|
||||
SERVER_START_REQ( set_fd_disp_info )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->unlink = info->DoDeleteFile;
|
||||
|
@ -2781,6 +2781,48 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
||||
case FileRenameInformation:
|
||||
if (len >= sizeof(FILE_RENAME_INFORMATION))
|
||||
{
|
||||
FILE_RENAME_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->RootDir;
|
||||
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->Replace && 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 );
|
||||
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;
|
||||
|
||||
default:
|
||||
FIXME("Unsupported class (%d)\n", class);
|
||||
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
||||
|
|
|
@ -1481,19 +1481,19 @@ static void test_file_rename_information(void)
|
|||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
ok( fileDeleted, "file should not 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 );
|
||||
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
todo_wine ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
|
||||
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
|
||||
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
HeapFree( GetProcessHeap(), 0, fni );
|
||||
|
||||
CloseHandle( handle );
|
||||
|
@ -1520,7 +1520,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1549,10 +1549,10 @@ static void test_file_rename_information(void)
|
|||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
ok( fileDeleted, "file should not exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
|
||||
|
@ -1583,7 +1583,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1617,7 +1617,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1651,19 +1651,19 @@ static void test_file_rename_information(void)
|
|||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
ok( fileDeleted, "file should not 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 );
|
||||
ok( res == STATUS_SUCCESS, "res expected STATUS_SUCCESS, got %x\n", res );
|
||||
fni->FileName[ fni->FileNameLength / sizeof(WCHAR) ] = 0;
|
||||
todo_wine ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
|
||||
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
ok( !lstrcmpW(fni->FileName, newpath + 2), "FileName expected %s, got %s\n",
|
||||
wine_dbgstr_w(newpath + 2), wine_dbgstr_w(fni->FileName) );
|
||||
HeapFree( GetProcessHeap(), 0, fni );
|
||||
|
||||
CloseHandle( handle );
|
||||
|
@ -1701,14 +1701,20 @@ static void test_file_rename_information(void)
|
|||
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" );
|
||||
todo_wine ok( !fileDeleted, "file should exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( fileDeleted, "file should not exist\n" );
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
|
||||
CloseHandle( handle );
|
||||
CloseHandle( handle2 );
|
||||
HeapFree( GetProcessHeap(), 0, fri );
|
||||
delete_object( oldpath );
|
||||
if (res == STATUS_SUCCESS) /* remove when Wine is fixed */
|
||||
{
|
||||
lstrcpyW( oldpath, newpath );
|
||||
lstrcatW( oldpath, foo_txtW );
|
||||
delete_object( oldpath );
|
||||
}
|
||||
delete_object( newpath );
|
||||
|
||||
/* oldpath is a directory, newpath is a file, Replace = FALSE */
|
||||
|
@ -1733,7 +1739,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1769,7 +1775,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1802,10 +1808,10 @@ static void test_file_rename_information(void)
|
|||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
ok( fileDeleted, "file should not exist\n" );
|
||||
fileDeleted = GetFileAttributesW( newpath ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||
ok( !fileDeleted, "file should exist\n" );
|
||||
|
||||
|
@ -1839,7 +1845,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1876,7 +1882,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1912,7 +1918,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1951,7 +1957,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -1985,7 +1991,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -2018,7 +2024,7 @@ static void test_file_rename_information(void)
|
|||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
|
@ -2051,12 +2057,12 @@ static void test_file_rename_information(void)
|
|||
|
||||
U(io).Status = 0xdeadbeef;
|
||||
res = pNtSetInformationFile( handle, &io, fri, sizeof(FILE_RENAME_INFORMATION) + fri->FileNameLength, FileRenameInformation );
|
||||
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;
|
||||
todo_wine ok( fileDeleted, "file should not exist\n" );
|
||||
ok( fileDeleted, "file should not 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 );
|
||||
|
|
|
@ -5080,14 +5080,29 @@ struct add_fd_completion_reply
|
|||
|
||||
|
||||
|
||||
struct set_fd_info_request
|
||||
struct set_fd_disp_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
int unlink;
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct set_fd_info_reply
|
||||
struct set_fd_disp_info_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_fd_name_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
obj_handle_t rootdir;
|
||||
/* VARARG(filename,string); */
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct set_fd_name_info_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
@ -5566,7 +5581,8 @@ enum request
|
|||
REQ_query_completion,
|
||||
REQ_set_completion_info,
|
||||
REQ_add_fd_completion,
|
||||
REQ_set_fd_info,
|
||||
REQ_set_fd_disp_info,
|
||||
REQ_set_fd_name_info,
|
||||
REQ_get_window_layered_info,
|
||||
REQ_set_window_layered_info,
|
||||
REQ_alloc_user_handle,
|
||||
|
@ -5841,7 +5857,8 @@ union generic_request
|
|||
struct query_completion_request query_completion_request;
|
||||
struct set_completion_info_request set_completion_info_request;
|
||||
struct add_fd_completion_request add_fd_completion_request;
|
||||
struct set_fd_info_request set_fd_info_request;
|
||||
struct set_fd_disp_info_request set_fd_disp_info_request;
|
||||
struct set_fd_name_info_request set_fd_name_info_request;
|
||||
struct get_window_layered_info_request get_window_layered_info_request;
|
||||
struct set_window_layered_info_request set_window_layered_info_request;
|
||||
struct alloc_user_handle_request alloc_user_handle_request;
|
||||
|
@ -6114,7 +6131,8 @@ union generic_reply
|
|||
struct query_completion_reply query_completion_reply;
|
||||
struct set_completion_info_reply set_completion_info_reply;
|
||||
struct add_fd_completion_reply add_fd_completion_reply;
|
||||
struct set_fd_info_reply set_fd_info_reply;
|
||||
struct set_fd_disp_info_reply set_fd_disp_info_reply;
|
||||
struct set_fd_name_info_reply set_fd_name_info_reply;
|
||||
struct get_window_layered_info_reply get_window_layered_info_reply;
|
||||
struct set_window_layered_info_reply set_window_layered_info_reply;
|
||||
struct alloc_user_handle_reply alloc_user_handle_reply;
|
||||
|
@ -6131,6 +6149,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 485
|
||||
#define SERVER_PROTOCOL_VERSION 486
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
105
server/fd.c
105
server/fd.c
|
@ -2254,6 +2254,84 @@ static void set_fd_disposition( struct fd *fd, int unlink )
|
|||
fd->closed->unlink = unlink || (fd->options & FILE_DELETE_ON_CLOSE);
|
||||
}
|
||||
|
||||
/* set new name for the fd */
|
||||
static void set_fd_name( struct fd *fd, struct fd *root, const char *nameptr, data_size_t len )
|
||||
{
|
||||
struct inode *inode;
|
||||
struct stat st;
|
||||
char *name;
|
||||
|
||||
if (!fd->inode || !fd->unix_name)
|
||||
{
|
||||
set_error( STATUS_OBJECT_TYPE_MISMATCH );
|
||||
return;
|
||||
}
|
||||
if (!len || ((nameptr[0] == '/') ^ !root))
|
||||
{
|
||||
set_error( STATUS_OBJECT_PATH_SYNTAX_BAD );
|
||||
return;
|
||||
}
|
||||
if (!(name = mem_alloc( len + 1 ))) return;
|
||||
memcpy( name, nameptr, len );
|
||||
name[len] = 0;
|
||||
|
||||
if (root)
|
||||
{
|
||||
char *combined_name = dup_fd_name( root, name );
|
||||
if (!combined_name)
|
||||
{
|
||||
set_error( STATUS_NO_MEMORY );
|
||||
goto failed;
|
||||
}
|
||||
free( name );
|
||||
name = combined_name;
|
||||
}
|
||||
|
||||
if (!stat( name, &st ))
|
||||
{
|
||||
/* can't replace directories or special files */
|
||||
if (!S_ISREG( st.st_mode ))
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* can't replace an opened file */
|
||||
if ((inode = get_inode( st.st_dev, st.st_ino, -1 )))
|
||||
{
|
||||
int is_empty = list_empty( &inode->open );
|
||||
release_object( inode );
|
||||
if (!is_empty)
|
||||
{
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* rename() cannot replace files with directories */
|
||||
if (fd->unix_fd != -1 && !fstat( fd->unix_fd, &st ) &&
|
||||
S_ISDIR( st.st_mode ) && unlink( name ))
|
||||
{
|
||||
file_set_error();
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
if (rename( fd->unix_name, name ))
|
||||
{
|
||||
file_set_error();
|
||||
goto failed;
|
||||
}
|
||||
|
||||
free( fd->unix_name );
|
||||
fd->unix_name = name;
|
||||
fd->closed->unix_name = name;
|
||||
return;
|
||||
|
||||
failed:
|
||||
free( name );
|
||||
}
|
||||
|
||||
struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key )
|
||||
{
|
||||
*p_key = fd->comp_key;
|
||||
|
@ -2450,8 +2528,8 @@ DECL_HANDLER(add_fd_completion)
|
|||
}
|
||||
}
|
||||
|
||||
/* set fd information */
|
||||
DECL_HANDLER(set_fd_info)
|
||||
/* set fd disposition information */
|
||||
DECL_HANDLER(set_fd_disp_info)
|
||||
{
|
||||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, DELETE );
|
||||
if (fd)
|
||||
|
@ -2460,3 +2538,26 @@ DECL_HANDLER(set_fd_info)
|
|||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
||||
/* set fd name information */
|
||||
DECL_HANDLER(set_fd_name_info)
|
||||
{
|
||||
struct fd *fd, *root_fd = NULL;
|
||||
|
||||
if (req->rootdir)
|
||||
{
|
||||
struct dir *root;
|
||||
|
||||
if (!(root = get_dir_obj( current->process, req->rootdir, 0 ))) return;
|
||||
root_fd = get_obj_fd( (struct object *)root );
|
||||
release_object( root );
|
||||
if (!root_fd) return;
|
||||
}
|
||||
|
||||
if ((fd = get_handle_fd_obj( current->process, req->handle, 0 )))
|
||||
{
|
||||
set_fd_name( fd, root_fd, get_req_data(), get_req_data_size() );
|
||||
release_object( fd );
|
||||
}
|
||||
if (root_fd) release_object( root_fd );
|
||||
}
|
||||
|
|
|
@ -3525,13 +3525,21 @@ enum coords_relative
|
|||
@END
|
||||
|
||||
|
||||
/* set fd information */
|
||||
@REQ(set_fd_info)
|
||||
/* set fd disposition information */
|
||||
@REQ(set_fd_disp_info)
|
||||
obj_handle_t handle; /* handle to a file or directory */
|
||||
int unlink; /* whether to unlink file on close */
|
||||
@END
|
||||
|
||||
|
||||
/* set fd name information */
|
||||
@REQ(set_fd_name_info)
|
||||
obj_handle_t handle; /* handle to a file or directory */
|
||||
obj_handle_t rootdir; /* root directory */
|
||||
VARARG(filename,string); /* new file name */
|
||||
@END
|
||||
|
||||
|
||||
/* Retrieve layered info for a window */
|
||||
@REQ(get_window_layered_info)
|
||||
user_handle_t handle; /* handle to the window */
|
||||
|
|
|
@ -359,7 +359,8 @@ DECL_HANDLER(remove_completion);
|
|||
DECL_HANDLER(query_completion);
|
||||
DECL_HANDLER(set_completion_info);
|
||||
DECL_HANDLER(add_fd_completion);
|
||||
DECL_HANDLER(set_fd_info);
|
||||
DECL_HANDLER(set_fd_disp_info);
|
||||
DECL_HANDLER(set_fd_name_info);
|
||||
DECL_HANDLER(get_window_layered_info);
|
||||
DECL_HANDLER(set_window_layered_info);
|
||||
DECL_HANDLER(alloc_user_handle);
|
||||
|
@ -633,7 +634,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_query_completion,
|
||||
(req_handler)req_set_completion_info,
|
||||
(req_handler)req_add_fd_completion,
|
||||
(req_handler)req_set_fd_info,
|
||||
(req_handler)req_set_fd_disp_info,
|
||||
(req_handler)req_set_fd_name_info,
|
||||
(req_handler)req_get_window_layered_info,
|
||||
(req_handler)req_set_window_layered_info,
|
||||
(req_handler)req_alloc_user_handle,
|
||||
|
@ -2223,9 +2225,12 @@ C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, cvalue) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, information) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, status) == 32 );
|
||||
C_ASSERT( sizeof(struct add_fd_completion_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_info_request, unlink) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_info_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, unlink) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_disp_info_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_name_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_name_info_request, rootdir) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_name_info_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_request, handle) == 12 );
|
||||
C_ASSERT( sizeof(struct get_window_layered_info_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_window_layered_info_reply, color_key) == 8 );
|
||||
|
|
|
@ -4136,12 +4136,19 @@ static void dump_add_fd_completion_request( const struct add_fd_completion_reque
|
|||
fprintf( stderr, ", status=%08x", req->status );
|
||||
}
|
||||
|
||||
static void dump_set_fd_info_request( const struct set_fd_info_request *req )
|
||||
static void dump_set_fd_disp_info_request( const struct set_fd_disp_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
fprintf( stderr, ", unlink=%d", req->unlink );
|
||||
}
|
||||
|
||||
static void dump_set_fd_name_info_request( const struct set_fd_name_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
fprintf( stderr, ", rootdir=%04x", req->rootdir );
|
||||
dump_varargs_string( ", filename=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_get_window_layered_info_request( const struct get_window_layered_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%08x", req->handle );
|
||||
|
@ -4515,7 +4522,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_query_completion_request,
|
||||
(dump_func)dump_set_completion_info_request,
|
||||
(dump_func)dump_add_fd_completion_request,
|
||||
(dump_func)dump_set_fd_info_request,
|
||||
(dump_func)dump_set_fd_disp_info_request,
|
||||
(dump_func)dump_set_fd_name_info_request,
|
||||
(dump_func)dump_get_window_layered_info_request,
|
||||
(dump_func)dump_set_window_layered_info_request,
|
||||
(dump_func)dump_alloc_user_handle_request,
|
||||
|
@ -4787,6 +4795,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_window_layered_info_reply,
|
||||
NULL,
|
||||
(dump_func)dump_alloc_user_handle_reply,
|
||||
|
@ -5057,7 +5066,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"query_completion",
|
||||
"set_completion_info",
|
||||
"add_fd_completion",
|
||||
"set_fd_info",
|
||||
"set_fd_disp_info",
|
||||
"set_fd_name_info",
|
||||
"get_window_layered_info",
|
||||
"set_window_layered_info",
|
||||
"alloc_user_handle",
|
||||
|
|
Loading…
Reference in New Issue