diff --git a/server/directory.c b/server/directory.c index cd9afb3c457..81d02d6f64e 100644 --- a/server/directory.c +++ b/server/directory.c @@ -249,14 +249,12 @@ static void create_session( unsigned int id ) static const WCHAR dir_bnolinksW[] = {'B','N','O','L','I','N','K','S'}; static const WCHAR dir_bnoW[] = {'B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s'}; static const WCHAR dir_dosdevicesW[] = {'D','o','s','D','e','v','i','c','e','s'}; - static const WCHAR dir_nlsW[] = {'N','L','S'}; static const WCHAR dir_windowsW[] = {'W','i','n','d','o','w','s'}; static const WCHAR dir_winstationsW[] = {'W','i','n','d','o','w','S','t','a','t','i','o','n','s'}; static const struct unicode_str dir_sessions_str = {dir_sessionsW, sizeof(dir_sessionsW)}; static const struct unicode_str dir_bnolinks_str = {dir_bnolinksW, sizeof(dir_bnolinksW)}; static const struct unicode_str dir_bno_str = {dir_bnoW, sizeof(dir_bnoW)}; static const struct unicode_str dir_dosdevices_str = {dir_dosdevicesW, sizeof(dir_dosdevicesW)}; - static const struct unicode_str dir_nls_str = {dir_nlsW, sizeof(dir_nlsW)}; static const struct unicode_str dir_windows_str = {dir_windowsW, sizeof(dir_windowsW)}; static const struct unicode_str dir_winstations_str = {dir_winstationsW, sizeof(dir_winstationsW)}; @@ -280,7 +278,6 @@ static void create_session( unsigned int id ) dir_bno_global = create_directory( &root_directory->obj, &dir_bno_str, OBJ_PERMANENT, HASH_SIZE, NULL ); dir_sessions = create_directory( &root_directory->obj, &dir_sessions_str, OBJ_PERMANENT, HASH_SIZE, NULL ); dir_bnolinks = create_directory( &dir_sessions->obj, &dir_bnolinks_str, OBJ_PERMANENT, HASH_SIZE, NULL ); - release_object( create_directory( &root_directory->obj, &dir_nls_str, OBJ_PERMANENT, HASH_SIZE, NULL )); release_object( dir_bno_global ); release_object( dir_bnolinks ); release_object( dir_sessions ); @@ -326,7 +323,7 @@ static void create_session( unsigned int id ) free( id_strW ); } -void init_directories(void) +void init_directories( struct fd *intl_fd ) { /* Directories */ static const WCHAR dir_globalW[] = {'?','?'}; @@ -334,11 +331,13 @@ void init_directories(void) static const WCHAR dir_deviceW[] = {'D','e','v','i','c','e'}; static const WCHAR dir_objtypeW[] = {'O','b','j','e','c','t','T','y','p','e','s'}; static const WCHAR dir_kernelW[] = {'K','e','r','n','e','l','O','b','j','e','c','t','s'}; + static const WCHAR dir_nlsW[] = {'N','L','S'}; static const struct unicode_str dir_global_str = {dir_globalW, sizeof(dir_globalW)}; static const struct unicode_str dir_driver_str = {dir_driverW, sizeof(dir_driverW)}; static const struct unicode_str dir_device_str = {dir_deviceW, sizeof(dir_deviceW)}; static const struct unicode_str dir_objtype_str = {dir_objtypeW, sizeof(dir_objtypeW)}; static const struct unicode_str dir_kernel_str = {dir_kernelW, sizeof(dir_kernelW)}; + static const struct unicode_str dir_nls_str = {dir_nlsW, sizeof(dir_nlsW)}; /* symlinks */ static const WCHAR link_dosdevW[] = {'D','o','s','D','e','v','i','c','e','s'}; @@ -399,10 +398,12 @@ void init_directories(void) static const struct unicode_str keyed_event_crit_sect_str = {keyed_event_crit_sectW, sizeof(keyed_event_crit_sectW)}; /* mappings */ + static const WCHAR intlW[] = {'N','l','s','S','e','c','t','i','o','n','L','A','N','G','_','I','N','T','L'}; static const WCHAR user_dataW[] = {'_','_','w','i','n','e','_','u','s','e','r','_','s','h','a','r','e','d','_','d','a','t','a'}; + static const struct unicode_str intl_str = {intlW, sizeof(intlW)}; static const struct unicode_str user_data_str = {user_dataW, sizeof(user_dataW)}; - struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel; + struct directory *dir_driver, *dir_device, *dir_global, *dir_kernel, *dir_nls; struct object *named_pipe_device, *mailslot_device, *null_device; unsigned int i; @@ -412,6 +413,7 @@ void init_directories(void) dir_objtype = create_directory( &root_directory->obj, &dir_objtype_str, OBJ_PERMANENT, HASH_SIZE, NULL ); dir_kernel = create_directory( &root_directory->obj, &dir_kernel_str, OBJ_PERMANENT, HASH_SIZE, NULL ); dir_global = create_directory( &root_directory->obj, &dir_global_str, OBJ_PERMANENT, HASH_SIZE, NULL ); + dir_nls = create_directory( &root_directory->obj, &dir_nls_str, OBJ_PERMANENT, HASH_SIZE, NULL ); /* devices */ named_pipe_device = create_named_pipe_device( &dir_device->obj, &named_pipe_str, OBJ_PERMANENT, NULL ); @@ -439,7 +441,8 @@ void init_directories(void) release_object( create_event( &dir_kernel->obj, &kernel_events[i], OBJ_PERMANENT, 1, 0, NULL )); release_object( create_keyed_event( &dir_kernel->obj, &keyed_event_crit_sect_str, OBJ_PERMANENT, NULL )); - /* user data mapping */ + /* mappings */ + release_object( create_fd_mapping( &dir_nls->obj, &intl_str, intl_fd, OBJ_PERMANENT, NULL )); release_object( create_user_data_mapping( &dir_kernel->obj, &user_data_str, OBJ_PERMANENT, NULL )); release_object( named_pipe_device ); @@ -450,6 +453,7 @@ void init_directories(void) release_object( dir_device ); release_object( dir_objtype ); release_object( dir_kernel ); + release_object( dir_nls ); release_object( dir_global ); } diff --git a/server/file.h b/server/file.h index 2fb634fad8d..69f2bed6cd6 100644 --- a/server/file.h +++ b/server/file.h @@ -171,6 +171,8 @@ extern struct file *get_mapping_file( struct process *process, client_ptr_t base extern const pe_image_info_t *get_mapping_image_info( struct process *process, client_ptr_t base ); extern void free_mapped_views( struct process *process ); extern int get_page_size(void); +extern struct mapping *create_fd_mapping( struct object *root, const struct unicode_str *name, struct fd *fd, + unsigned int attr, const struct security_descriptor *sd ); extern struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, const struct security_descriptor *sd ); diff --git a/server/main.c b/server/main.c index 5d7881a6af9..d7aed0da199 100644 --- a/server/main.c +++ b/server/main.c @@ -144,8 +144,7 @@ int main( int argc, char *argv[] ) if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); set_current_time(); init_signals(); - load_intl_file(); - init_directories(); + init_directories( load_intl_file() ); init_registry(); main_loop(); return 0; diff --git a/server/mapping.c b/server/mapping.c index 769a986ae21..6c2e7a1fd2b 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -883,6 +883,41 @@ static struct mapping *create_mapping( struct object *root, const struct unicode return NULL; } +/* create a read-only file mapping for the specified fd */ +struct mapping *create_fd_mapping( struct object *root, const struct unicode_str *name, + struct fd *fd, unsigned int attr, const struct security_descriptor *sd ) +{ + struct mapping *mapping; + int unix_fd; + struct stat st; + + if (!(mapping = create_named_object( root, &mapping_ops, name, attr, sd ))) return NULL; + if (get_error() == STATUS_OBJECT_NAME_EXISTS) return mapping; /* Nothing else to do */ + + mapping->shared = NULL; + mapping->committed = NULL; + mapping->flags = SEC_FILE; + mapping->fd = (struct fd *)grab_object( fd ); + set_fd_user( mapping->fd, &mapping_fd_ops, NULL ); + + if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error; + if (fstat( unix_fd, &st ) == -1) + { + file_set_error(); + goto error; + } + if (!(mapping->size = st.st_size)) + { + set_error( STATUS_MAPPED_FILE_SIZE_ZERO ); + goto error; + } + return mapping; + + error: + release_object( mapping ); + return NULL; +} + static struct mapping *get_mapping_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct mapping *)get_handle_obj( process, handle, access, &mapping_ops ); diff --git a/server/object.h b/server/object.h index 3b3e9084798..73058fd3f99 100644 --- a/server/object.h +++ b/server/object.h @@ -244,7 +244,7 @@ extern struct object *get_root_directory(void); extern struct object *get_directory_obj( struct process *process, obj_handle_t handle ); extern struct object_type *get_object_type( const struct unicode_str *name ); extern int directory_link_name( struct object *obj, struct object_name *name, struct object *parent ); -extern void init_directories(void); +extern void init_directories( struct fd *intl_fd ); /* symbolic link functions */ diff --git a/server/unicode.c b/server/unicode.c index 0dde757313b..56f3c024103 100644 --- a/server/unicode.c +++ b/server/unicode.c @@ -23,9 +23,13 @@ #include #include +#include +#include "windef.h" +#include "winternl.h" #include "request.h" #include "unicode.h" +#include "file.h" /* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */ static const char utf8_length[128] = @@ -257,13 +261,15 @@ static char *get_nls_dir(void) } /* load the case mapping table */ -void load_intl_file(void) +struct fd *load_intl_file(void) { static const char *nls_dirs[] = { NULL, NLSDIR, "/usr/local/share/wine/nls", "/usr/share/wine/nls" }; unsigned int i, offset, size; unsigned short data; char *path; - int unix_fd = -1; + struct fd *fd = NULL; + int unix_fd; + mode_t mode = 0600; nls_dirs[0] = get_nls_dir(); for (i = 0; i < ARRAY_SIZE( nls_dirs ); i++) @@ -272,10 +278,13 @@ void load_intl_file(void) if (!(path = malloc( strlen(nls_dirs[i]) + sizeof("/l_intl.nls" )))) continue; strcpy( path, nls_dirs[i] ); strcat( path, "/l_intl.nls" ); - if ((unix_fd = open( path, O_RDONLY )) != -1) break; + if ((fd = open_fd( NULL, path, O_RDONLY, &mode, FILE_READ_DATA, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) break; free( path ); } - if (unix_fd == -1) fatal_error( "failed to load l_intl.nls\n" ); + if (!fd) fatal_error( "failed to load l_intl.nls\n" ); + unix_fd = get_unix_fd( fd ); /* read initial offset */ if (pread( unix_fd, &data, sizeof(data), 0 ) != sizeof(data) || !data) goto failed; offset = data; @@ -289,9 +298,8 @@ void load_intl_file(void) /* read lowercase table */ if (!(casemap = malloc( size * 2 ))) goto failed; if (pread( unix_fd, casemap, size * 2, offset * 2 ) != size * 2) goto failed; - close( unix_fd ); free( path ); - return; + return fd; failed: fatal_error( "invalid format for casemap table %s\n", path ); diff --git a/server/unicode.h b/server/unicode.h index ddbbe4b5cfc..e031d6ef0cf 100644 --- a/server/unicode.h +++ b/server/unicode.h @@ -31,6 +31,6 @@ extern unsigned int hash_strW( const WCHAR *str, data_size_t len, unsigned int h extern WCHAR *ascii_to_unicode_str( const char *str, struct unicode_str *ret ); extern int parse_strW( WCHAR *buffer, data_size_t *len, const char *src, char endchar ); extern int dump_strW( const WCHAR *str, data_size_t len, FILE *f, const char escape[2] ); -extern void load_intl_file(void); +extern struct fd *load_intl_file(void); #endif /* __WINE_SERVER_UNICODE_H */