From 014099caf5a8a0555846720260dd24b6d6ec2020 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 12 Mar 2004 01:56:49 +0000 Subject: [PATCH] Changed the create_file server request to take NtCreateFile flags instead of CreateFileW ones (based on a patch by Eric Pouech). --- dlls/winedos/int21.c | 3 +- files/file.c | 27 +++++++++++++- include/wine/server_protocol.h | 3 +- include/winternl.h | 60 +++++++++++++++++++++++-------- server/file.c | 66 +++++++++++++++++----------------- server/protocol.def | 1 + server/trace.c | 1 + 7 files changed, 112 insertions(+), 49 deletions(-) diff --git a/dlls/winedos/int21.c b/dlls/winedos/int21.c index 4d907b71993..13ef7f9e240 100644 --- a/dlls/winedos/int21.c +++ b/dlls/winedos/int21.c @@ -821,7 +821,8 @@ static HANDLE INT21_CreateMagicDeviceHandle( LPCWSTR name ) req->access = GENERIC_READ|GENERIC_WRITE; req->inherit = 0; req->sharing = FILE_SHARE_READ|FILE_SHARE_WRITE; - req->create = OPEN_ALWAYS; + req->create = FILE_OPEN_IF; + req->options = FILE_SYNCHRONOUS_IO_ALERT; req->attrs = 0; req->removable = 0; wine_server_add_data( req, unix_name, strlen(unix_name) ); diff --git a/files/file.c b/files/file.c index 219d9bd2bcd..8ad74aff87f 100644 --- a/files/file.c +++ b/files/file.c @@ -184,8 +184,32 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing, UINT drive_type ) { unsigned int err; + UINT disp, options; HANDLE ret; + switch (creation) + { + case CREATE_ALWAYS: disp = FILE_OVERWRITE_IF; break; + case CREATE_NEW: disp = FILE_CREATE; break; + case OPEN_ALWAYS: disp = FILE_OPEN_IF; break; + case OPEN_EXISTING: disp = FILE_OPEN; break; + case TRUNCATE_EXISTING: disp = FILE_OVERWRITE; break; + default: + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + } + + options = 0; + if (attributes & FILE_FLAG_BACKUP_SEMANTICS) + options |= FILE_OPEN_FOR_BACKUP_INTENT; + if (attributes & FILE_FLAG_DELETE_ON_CLOSE) + options |= FILE_DELETE_ON_CLOSE; + if (!(attributes & FILE_FLAG_OVERLAPPED)) + options |= FILE_SYNCHRONOUS_IO_ALERT; + if (attributes & FILE_FLAG_RANDOM_ACCESS) + options |= FILE_RANDOM_ACCESS; + attributes &= FILE_ATTRIBUTE_VALID_FLAGS; + for (;;) { SERVER_START_REQ( create_file ) @@ -193,7 +217,8 @@ HANDLE FILE_CreateFile( LPCSTR filename, DWORD access, DWORD sharing, req->access = access; req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle); req->sharing = sharing; - req->create = creation; + req->create = disp; + req->options = options; req->attrs = attributes; req->removable = (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM); wine_server_add_data( req, filename, strlen(filename) ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 7703d8757ce..9ee99545f55 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -751,6 +751,7 @@ struct create_file_request int inherit; unsigned int sharing; int create; + unsigned int options; unsigned int attrs; int removable; /* VARARG(filename,string); */ @@ -3729,6 +3730,6 @@ union generic_reply struct set_global_windows_reply set_global_windows_reply; }; -#define SERVER_PROTOCOL_VERSION 133 +#define SERVER_PROTOCOL_VERSION 134 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winternl.h b/include/winternl.h index 274930c8afc..3c8d64f147d 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -900,22 +900,54 @@ typedef struct _LDR_RESOURCE_INFO */ /* flags for NtCreateFile and NtOpenFile */ -#define FILE_DIRECTORY_FLAG 0x00000001 -#define FILE_WRITE_THROUGH 0x00000002 -#define FILE_SEQUENTIAL_ONLY 0x00000004 -#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 -#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 -#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 -#define FILE_NON_DIRECTORY_FILE 0x00000040 -#define FILE_CREATE_TREE_CONNECTION 0x00000080 +#define FILE_DIRECTORY_FILE 0x00000001 +#define FILE_WRITE_THROUGH 0x00000002 +#define FILE_SEQUENTIAL_ONLY 0x00000004 +#define FILE_NO_INTERMEDIATE_BUFFERING 0x00000008 +#define FILE_SYNCHRONOUS_IO_ALERT 0x00000010 +#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 +#define FILE_NON_DIRECTORY_FILE 0x00000040 +#define FILE_CREATE_TREE_CONNECTION 0x00000080 +#define FILE_COMPLETE_IF_OPLOCKED 0x00000100 +#define FILE_NO_EA_KNOWLEDGE 0x00000200 +#define FILE_OPEN_FOR_RECOVERY 0x00000400 +#define FILE_RANDOM_ACCESS 0x00000800 +#define FILE_DELETE_ON_CLOSE 0x00001000 +#define FILE_OPEN_BY_FILE_ID 0x00002000 +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#define FILE_NO_COMPRESSION 0x00008000 +#define FILE_RESERVE_OPFILTER 0x00100000 +#define FILE_TRANSACTED_MODE 0x00200000 +#define FILE_OPEN_OFFLINE_FILE 0x00400000 + +#define FILE_ATTRIBUTE_VALID_FLAGS 0x00007fb7 +#define FILE_ATTRIBUTE_VALID_SET_FLAGS 0x000031a7 /* status for NtCreateFile or NtOpenFile */ -#define FILE_SUPERSEDED 0x00000000 -#define FILE_OPENED 0x00000001 -#define FILE_CREATED 0x00000002 -#define FILE_OVERWRITTEN 0x00000003 -#define FILE_EXISTS 0x00000004 -#define FILE_DOES_NOT_EXIST 0x00000005 +#define FILE_SUPERSEDED 0 +#define FILE_OPENED 1 +#define FILE_CREATED 2 +#define FILE_OVERWRITTEN 3 +#define FILE_EXISTS 4 +#define FILE_DOES_NOT_EXIST 5 + +/* disposition for NtCreateFile */ +#define FILE_SUPERSEDE 0 +#define FILE_OPEN 1 +#define FILE_CREATE 2 +#define FILE_OPEN_IF 3 +#define FILE_OVERWRITE 4 +#define FILE_OVERWRITE_IF 5 +#define FILE_MAXIMUM_DISPOSITION 5 + +/* Characteristics of a File System */ +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 #if (_WIN32_WINNT >= 0x0501) #define INTERNAL_TS_ACTIVE_CONSOLE_ID ( *((volatile ULONG*)(0x7ffe02d8)) ) diff --git a/server/file.c b/server/file.c index 4dfff91b02b..a22d269f217 100644 --- a/server/file.c +++ b/server/file.c @@ -43,6 +43,8 @@ #include "winerror.h" #include "windef.h" #include "winbase.h" +#include "winreg.h" +#include "winternl.h" #include "file.h" #include "handle.h" @@ -57,9 +59,9 @@ struct file struct file *next; /* next file in hashing list */ char *name; /* file name */ unsigned int access; /* file access (GENERIC_READ/WRITE) */ - unsigned int flags; /* flags (FILE_FLAG_*) */ + unsigned int options; /* file options (FILE_DELETE_ON_CLOSE, FILE_SYNCHRONOUS...) */ unsigned int sharing; /* file sharing mode */ - int removable; /* is file on removable media? */ + int removable; /* is file on removable media? */ struct async_queue read_q; struct async_queue write_q; }; @@ -99,6 +101,11 @@ static const struct fd_ops file_fd_ops = file_queue_async /* queue_async */ }; +static inline int is_overlapped( const struct file *file ) +{ + return !(file->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)); +} + static int get_name_hash( const char *name ) { int hash = 0; @@ -133,8 +140,7 @@ static int check_sharing( const char *name, int hash, unsigned int access, /* create a file from a file descriptor */ /* if the function fails the fd is closed */ -static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing, - unsigned int attrs, int removable ) +static struct file *create_file_for_fd( int fd, unsigned int access, unsigned int sharing ) { struct file *file; @@ -143,14 +149,9 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in file->name = NULL; file->next = NULL; file->access = access; - file->flags = attrs; + file->options = FILE_SYNCHRONOUS_IO_NONALERT; file->sharing = sharing; - file->removable = removable; - if (file->flags & FILE_FLAG_OVERLAPPED) - { - init_async_queue (&file->read_q); - init_async_queue (&file->write_q); - } + file->removable = 0; if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj ))) { release_object( file ); @@ -162,8 +163,8 @@ static struct file *create_file_for_fd( int fd, unsigned int access, unsigned in static struct file *create_file( const char *nameptr, size_t len, unsigned int access, - unsigned int sharing, int create, unsigned int attrs, - int removable ) + unsigned int sharing, int create, unsigned int options, + unsigned int attrs, int removable ) { struct file *file; int hash, flags; @@ -180,11 +181,12 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a switch(create) { - case CREATE_NEW: flags = O_CREAT | O_EXCL; break; - case CREATE_ALWAYS: flags = O_CREAT | O_TRUNC; break; - case OPEN_ALWAYS: flags = O_CREAT; break; - case TRUNCATE_EXISTING: flags = O_TRUNC; break; - case OPEN_EXISTING: flags = 0; break; + case FILE_CREATE: flags = O_CREAT | O_EXCL; break; + case FILE_OVERWRITE_IF: /* FIXME: the difference is whether we trash existing attr or not */ + case FILE_SUPERSEDE: flags = O_CREAT | O_TRUNC; break; + case FILE_OPEN: flags = 0; break; + case FILE_OPEN_IF: flags = O_CREAT; break; + case FILE_OVERWRITE: flags = O_TRUNC; break; default: set_error( STATUS_INVALID_PARAMETER ); goto error; } switch(access & (GENERIC_READ | GENERIC_WRITE)) @@ -203,13 +205,13 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a if (!(file = alloc_object( &file_ops ))) goto error; file->access = access; - file->flags = attrs; + file->options = options; file->sharing = sharing; file->removable = removable; file->name = name; file->next = file_hash[hash]; file_hash[hash] = file; - if (file->flags & FILE_FLAG_OVERLAPPED) + if (is_overlapped( file )) { init_async_queue (&file->read_q); init_async_queue (&file->write_q); @@ -223,7 +225,7 @@ static struct file *create_file( const char *nameptr, size_t len, unsigned int a return NULL; } /* refuse to open a directory */ - if (S_ISDIR(mode) && !(file->flags & FILE_FLAG_BACKUP_SEMANTICS)) + if (S_ISDIR(mode) && !(options & FILE_OPEN_FOR_BACKUP_INTENT)) { set_error( STATUS_ACCESS_DENIED ); release_object( file ); @@ -262,14 +264,14 @@ struct file *create_temp_file( int access ) return NULL; } unlink( tmpfn ); - return create_file_for_fd( fd, access, 0, 0, FALSE ); + return create_file_for_fd( fd, access, 0 ); } static void file_dump( struct object *obj, int verbose ) { struct file *file = (struct file *)obj; assert( obj->ops == &file_ops ); - fprintf( stderr, "File fd=%p flags=%08x name='%s'\n", file->fd, file->flags, file->name ); + fprintf( stderr, "File fd=%p options=%08x name='%s'\n", file->fd, file->options, file->name ); } static int file_get_poll_events( struct fd *fd ) @@ -286,7 +288,7 @@ static void file_poll_event( struct fd *fd, int event ) { struct file *file = get_fd_user( fd ); assert( file->obj.ops == &file_ops ); - if ( file->flags & FILE_FLAG_OVERLAPPED ) + if (is_overlapped( file )) { if( IS_READY(file->read_q) && (POLLIN & event) ) { @@ -354,7 +356,7 @@ static int file_get_info( struct fd *fd, struct get_file_info_reply *reply, int reply->serial = 0; /* FIXME */ } *flags = 0; - if (file->flags & FILE_FLAG_OVERLAPPED) *flags |= FD_FLAG_OVERLAPPED; + if (is_overlapped( file )) *flags |= FD_FLAG_OVERLAPPED; return FD_TYPE_DEFAULT; } @@ -366,7 +368,7 @@ static void file_queue_async(struct fd *fd, void *ptr, unsigned int status, int assert( file->obj.ops == &file_ops ); - if ( !(file->flags & FILE_FLAG_OVERLAPPED) ) + if (!is_overlapped( file )) { set_error ( STATUS_INVALID_HANDLE ); return; @@ -429,10 +431,10 @@ static void file_destroy( struct object *obj ) while (*pptr && *pptr != file) pptr = &(*pptr)->next; assert( *pptr ); *pptr = (*pptr)->next; - if (file->flags & FILE_FLAG_DELETE_ON_CLOSE) unlink( file->name ); + if (file->options & FILE_DELETE_ON_CLOSE) unlink( file->name ); free( file->name ); } - if (file->flags & FILE_FLAG_OVERLAPPED) + if (is_overlapped( file )) { destroy_async_queue (&file->read_q); destroy_async_queue (&file->write_q); @@ -462,6 +464,7 @@ void file_set_error(void) case ESPIPE: set_win32_error( ERROR_SEEK ); break; case ENOTEMPTY: set_error( STATUS_DIRECTORY_NOT_EMPTY ); break; case EIO: set_error( STATUS_ACCESS_VIOLATION ); break; + case ENOTDIR: set_error( STATUS_NOT_A_DIRECTORY ); break; #ifdef EOVERFLOW case EOVERFLOW: set_error( STATUS_INVALID_PARAMETER ); break; #endif @@ -600,7 +603,7 @@ DECL_HANDLER(create_file) reply->handle = 0; if ((file = create_file( get_req_data(), get_req_data_size(), req->access, - req->sharing, req->create, req->attrs, req->removable ))) + req->sharing, req->create, req->options, req->attrs, req->removable ))) { reply->handle = alloc_handle( current->process, file, req->access, req->inherit ); release_object( file ); @@ -619,8 +622,7 @@ DECL_HANDLER(alloc_file_handle) set_error( STATUS_INVALID_HANDLE ); return; } - if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, FALSE ))) + if ((file = create_file_for_fd( fd, req->access, FILE_SHARE_READ | FILE_SHARE_WRITE ))) { reply->handle = alloc_handle( current->process, file, req->access, req->inherit ); release_object( file ); @@ -665,7 +667,7 @@ DECL_HANDLER(lock_file) if ((file = get_file_obj( current->process, req->handle, 0 ))) { reply->handle = lock_fd( file->fd, offset, count, req->shared, req->wait ); - reply->overlapped = (file->flags & FILE_FLAG_OVERLAPPED) != 0; + reply->overlapped = is_overlapped( file ); release_object( file ); } } diff --git a/server/protocol.def b/server/protocol.def index cc0c7d67e19..22535548725 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -575,6 +575,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; int inherit; /* inherit flag */ unsigned int sharing; /* sharing flags */ int create; /* file create action */ + unsigned int options; /* file options */ unsigned int attrs; /* file attributes for creation */ int removable; /* is file on removable media? */ VARARG(filename,string); /* file name */ diff --git a/server/trace.c b/server/trace.c index 889ad7c846b..30f0f31b5fa 100644 --- a/server/trace.c +++ b/server/trace.c @@ -835,6 +835,7 @@ static void dump_create_file_request( const struct create_file_request *req ) fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " sharing=%08x,", req->sharing ); fprintf( stderr, " create=%d,", req->create ); + fprintf( stderr, " options=%08x,", req->options ); fprintf( stderr, " attrs=%08x,", req->attrs ); fprintf( stderr, " removable=%d,", req->removable ); fprintf( stderr, " filename=" );