Repaired shared PE data sections.
diff --git a/server/file.c b/server/file.c index 75b1dd8..6ffba87 100644 --- a/server/file.c +++ b/server/file.c
@@ -181,6 +181,12 @@ return NULL; } +/* check if two file objects point to the same file */ +int is_same_file( struct file *file1, struct file *file2 ) +{ + return !strcmp( file1->name, file2->name ); +} + /* Create an anonymous Unix file */ int create_anonymous_file(void) {
diff --git a/server/mapping.c b/server/mapping.c index 2bfdd77..c87c6d3 100644 --- a/server/mapping.c +++ b/server/mapping.c
@@ -19,15 +19,17 @@ struct mapping { - struct object obj; /* object header */ - int size_high; /* mapping size */ - int size_low; /* mapping size */ - int protect; /* protection flags */ - struct file *file; /* file mapped */ - int header_size; /* size of headers (for PE image mapping) */ - void *base; /* default base addr (for PE image mapping) */ - struct file *shared_file; /* temp file for shared PE mapping */ - int shared_size; /* shared mapping total size */ + struct object obj; /* object header */ + int size_high; /* mapping size */ + int size_low; /* mapping size */ + int protect; /* protection flags */ + struct file *file; /* file mapped */ + int header_size; /* size of headers (for PE image mapping) */ + void *base; /* default base addr (for PE image mapping) */ + struct file *shared_file; /* temp file for shared PE mapping */ + int shared_size; /* shared mapping total size */ + struct mapping *shared_next; /* next in shared PE mapping list */ + struct mapping *shared_prev; /* prev in shared PE mapping list */ }; static int mapping_get_fd( struct object *obj ); @@ -50,6 +52,8 @@ mapping_destroy /* destroy */ }; +static struct mapping *shared_first; + #ifdef __i386__ /* These are always the same on an i386, and it will be faster this way */ @@ -99,6 +103,17 @@ return obj->ops->get_fd( obj ); } +/* find the shared PE mapping for a given mapping */ +static struct file *get_shared_file( struct mapping *mapping ) +{ + struct mapping *ptr; + + for (ptr = shared_first; ptr; ptr = ptr->shared_next) + if (is_same_file( ptr->file, mapping->file )) + return (struct file *)grab_object( ptr->shared_file ); + return NULL; +} + /* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, int nb_sec ) @@ -123,6 +138,8 @@ } if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */ + if ((mapping->shared_file = get_shared_file( mapping ))) return 1; + /* create a temp file for the mapping */ if (!(mapping->shared_file = create_temp_file( GENERIC_READ|GENERIC_WRITE ))) goto error; @@ -185,6 +202,13 @@ if (!build_shared_mapping( mapping, fd, sec, nt.FileHeader.NumberOfSections )) goto error; + if (mapping->shared_file) /* link it in the list */ + { + if ((mapping->shared_next = shared_first)) shared_first->shared_prev = mapping; + mapping->shared_prev = NULL; + shared_first = mapping; + } + mapping->size_low = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage ); mapping->size_high = 0; mapping->base = (void *)nt.OptionalHeader.ImageBase; @@ -290,7 +314,13 @@ struct mapping *mapping = (struct mapping *)obj; assert( obj->ops == &mapping_ops ); if (mapping->file) release_object( mapping->file ); - if (mapping->shared_file) release_object( mapping->shared_file ); + if (mapping->shared_file) + { + release_object( mapping->shared_file ); + if (mapping->shared_next) mapping->shared_next->shared_prev = mapping->shared_prev; + if (mapping->shared_prev) mapping->shared_prev->shared_next = mapping->shared_next; + else shared_first = mapping->shared_next; + } } int get_page_size(void)
diff --git a/server/object.h b/server/object.h index 2b3a02a..995e602 100644 --- a/server/object.h +++ b/server/object.h
@@ -148,6 +148,7 @@ extern struct file *get_file_obj( struct process *process, handle_t handle, unsigned int access ); +extern int is_same_file( struct file *file1, struct file *file2 ); extern int grow_file( struct file *file, int size_high, int size_low ); extern int create_anonymous_file(void); extern struct file *create_temp_file( int access );