Mike McCormack : kernel32: Create a simple abstraction for file
mappings.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Jan 11 05:34:12 CST 2007
Module: wine
Branch: master
Commit: 8f8fecd00e37d1869485d40b93f891f3872682fa
URL: http://source.winehq.org/git/wine.git/?a=commit;h=8f8fecd00e37d1869485d40b93f891f3872682fa
Author: Mike McCormack <mike at codeweavers.com>
Date: Thu Jan 11 17:41:21 2007 +0900
kernel32: Create a simple abstraction for file mappings.
---
dlls/kernel32/resource.c | 175 ++++++++++++++++++++++++++++++----------------
1 files changed, 116 insertions(+), 59 deletions(-)
diff --git a/dlls/kernel32/resource.c b/dlls/kernel32/resource.c
index fdf06a7..d8d1afb 100644
--- a/dlls/kernel32/resource.c
+++ b/dlls/kernel32/resource.c
@@ -910,6 +910,105 @@ struct resource_size_info {
DWORD total_size;
};
+struct mapping_info {
+ HANDLE file;
+ HANDLE mapping;
+ void *base;
+ DWORD size;
+ BOOL read_write;
+};
+
+static BOOL map_file_into_memory( struct mapping_info *mi )
+{
+ DWORD page_attr, perm;
+
+ if (mi->read_write)
+ {
+ page_attr = PAGE_READWRITE;
+ perm = FILE_MAP_WRITE | FILE_MAP_READ;
+ }
+ else
+ {
+ page_attr = PAGE_READONLY;
+ perm = FILE_MAP_READ;
+ }
+
+ mi->mapping = CreateFileMappingW( mi->file, NULL, page_attr, 0, 0, NULL );
+ if (!mi->mapping)
+ return FALSE;
+
+ mi->base = MapViewOfFile( mi->mapping, perm, 0, 0, mi->size );
+ if (!mi->base)
+ return FALSE;
+
+ return TRUE;
+}
+
+static BOOL unmap_file_from_memory( struct mapping_info *mi )
+{
+ if (mi->base)
+ UnmapViewOfFile( mi->base );
+ mi->base = NULL;
+ if (mi->mapping)
+ CloseHandle( mi->mapping );
+ mi->mapping = NULL;
+ return TRUE;
+}
+
+static void destroy_mapping( struct mapping_info *mi )
+{
+ if (!mi)
+ return;
+ unmap_file_from_memory( mi );
+ if (mi->file)
+ CloseHandle( mi->file );
+ HeapFree( GetProcessHeap(), 0, mi );
+}
+
+static struct mapping_info *create_mapping( LPCWSTR name, BOOL rw )
+{
+ struct mapping_info *mi;
+
+ mi = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof *mi );
+ if (!mi)
+ return NULL;
+
+ mi->read_write = rw;
+
+ mi->file = CreateFileW( name, GENERIC_READ | (rw ? GENERIC_WRITE : 0),
+ 0, NULL, OPEN_EXISTING, 0, 0 );
+
+ if (mi->file != INVALID_HANDLE_VALUE)
+ {
+ mi->size = GetFileSize( mi->file, NULL );
+
+ if (map_file_into_memory( mi ))
+ return mi;
+ }
+
+ unmap_file_from_memory( mi );
+
+ return NULL;
+}
+
+static BOOL resize_mapping( struct mapping_info *mi, DWORD new_size )
+{
+ if (!unmap_file_from_memory( mi ))
+ return FALSE;
+
+ /* change the file size */
+ SetFilePointer( mi->file, new_size, NULL, FILE_BEGIN );
+ if (!SetEndOfFile( mi->file ))
+ {
+ ERR("failed to set file size to %08x\n", new_size );
+ return FALSE;
+ }
+
+ mi->size = new_size;
+
+ return map_file_into_memory( mi );
+}
+
static void get_resource_sizes( QUEUEDUPDATES *updates, struct resource_size_info *si )
{
struct resource_dir_entry *types, *names;
@@ -1169,13 +1268,12 @@ static BOOL write_raw_resources( QUEUEDU
static const WCHAR prefix[] = { 'r','e','s','u',0 };
WCHAR tempdir[MAX_PATH], tempfile[MAX_PATH];
DWORD mapping_size, section_size, old_size;
- HANDLE file = NULL, mapping = NULL;
BOOL ret = FALSE;
- void *base = NULL;
IMAGE_SECTION_HEADER *sec;
IMAGE_NT_HEADERS *nt;
struct resource_size_info res_size;
BYTE *res_base;
+ struct mapping_info *write_map = NULL;
/* copy the exe to a temp file then update the temp file... */
tempdir[0] = 0;
@@ -1190,21 +1288,11 @@ static BOOL write_raw_resources( QUEUEDU
TRACE("tempfile %s\n", debugstr_w(tempfile));
- file = CreateFileW( tempfile, GENERIC_READ | GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING, 0, 0 );
-
- mapping_size = GetFileSize( file, NULL );
- old_size = mapping_size;
-
- mapping = CreateFileMappingW( file, NULL, PAGE_READWRITE, 0, 0, NULL );
- if (!mapping)
- goto done;
-
- base = MapViewOfFile( mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, mapping_size );
- if (!base)
+ write_map = create_mapping( tempfile, TRUE );
+ if (!write_map)
goto done;
- nt = get_nt_header( base, mapping_size );
+ nt = get_nt_header( write_map->base, write_map->size );
if (!nt)
goto done;
@@ -1214,14 +1302,14 @@ static BOOL write_raw_resources( QUEUEDU
goto done;
}
- sec = get_resource_section( base, mapping_size );
+ sec = get_resource_section( write_map->base, write_map->size );
if (!sec)
- goto done;
+ goto done;
- if ((sec->SizeOfRawData + sec->PointerToRawData) != mapping_size)
+ if ((sec->SizeOfRawData + sec->PointerToRawData) != write_map->size)
{
FIXME(".rsrc isn't at the end of the image %08x + %08x != %08x\n",
- sec->SizeOfRawData, sec->PointerToRawData, mapping_size);
+ sec->SizeOfRawData, sec->PointerToRawData, write_map->size);
goto done;
}
@@ -1240,43 +1328,22 @@ static BOOL write_raw_resources( QUEUEDU
/* check if the file size needs to be changed */
if (section_size != sec->SizeOfRawData)
{
+ old_size = write_map->size;
+
TRACE("file size %08x -> %08x\n", old_size, mapping_size);
/* unmap the file before changing the file size */
- UnmapViewOfFile( base );
- base = NULL;
- CloseHandle( mapping );
- mapping = NULL;
-
- /* change the file size */
- SetFilePointer( file, mapping_size, NULL, FILE_BEGIN );
- if (!SetEndOfFile( file ))
- {
- ERR("failed to set file size to %08x\n", mapping_size );
- goto done;
- }
-
- mapping = CreateFileMappingW( file, NULL, PAGE_READWRITE, 0, 0, NULL );
- if (!mapping)
- goto done;
-
- /* remap the file */
- base = MapViewOfFile( mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, mapping_size );
- if (!base)
- {
- ERR("failed to map file again\n");
- goto done;
- }
+ ret = resize_mapping( write_map, mapping_size );
/* get the pointers again - they might be different after remapping */
- nt = get_nt_header( base, mapping_size );
+ nt = get_nt_header( write_map->base, mapping_size );
if (!nt)
{
ERR("couldn't get NT header\n");
goto done;
}
- sec = get_resource_section( base, mapping_size );
+ sec = get_resource_section( write_map->base, mapping_size );
if (!sec)
goto done;
@@ -1285,12 +1352,12 @@ static BOOL write_raw_resources( QUEUEDU
sec->SizeOfRawData = section_size;
sec->Misc.VirtualSize = section_size;
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = res_size.total_size;
- nt->OptionalHeader.SizeOfInitializedData = get_init_data_size( base, mapping_size );
+ nt->OptionalHeader.SizeOfInitializedData = get_init_data_size( write_map->base, mapping_size );
}
- res_base = (LPBYTE) base + sec->PointerToRawData;
+ res_base = (LPBYTE) write_map->base + sec->PointerToRawData;
- TRACE("base = %p offset = %08x\n", base, sec->PointerToRawData);
+ TRACE("base = %p offset = %08x\n", write_map->base, sec->PointerToRawData);
ret = write_resources( updates, res_base, &res_size, sec->VirtualAddress );
@@ -1299,17 +1366,7 @@ static BOOL write_raw_resources( QUEUEDU
TRACE("after .rsrc at %08x, size %08x\n", sec->PointerToRawData, sec->SizeOfRawData);
done:
- if (base)
- {
- FlushViewOfFile( base, mapping_size );
- UnmapViewOfFile( base );
- }
-
- if (mapping)
- CloseHandle( mapping );
-
- if (file)
- CloseHandle( file );
+ destroy_mapping( write_map );
if (ret)
ret = CopyFileW( tempfile, updates->pFileName, FALSE );
More information about the wine-cvs
mailing list