From cdaac43d3a9f339ccf0f27c2fdab7f7b191d0ebd Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Thu, 25 Jun 2020 14:44:15 +0000 Subject: [PATCH] Windows: fix eina_file_map_new() the offset passed to MapViewOfFile() must be a multiple of the granularity. https://docs.microsoft.com/en-us/windows/win32/memory/creating-a-view-within-a-file is taken as basis for this patch Reviewed-by: Stefan Schmidt Reviewed-by: Wander Lairson Costa Differential Revision: https://phab.enlightenment.org/D12031 --- src/lib/eina/eina_file_common.h | 3 ++ src/lib/eina/eina_file_win32.c | 64 ++++++++++++++++++++++----------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/lib/eina/eina_file_common.h b/src/lib/eina/eina_file_common.h index 9aedfae755..16fb772c4d 100644 --- a/src/lib/eina/eina_file_common.h +++ b/src/lib/eina/eina_file_common.h @@ -124,6 +124,9 @@ struct _Eina_File_Map Eina_Bool hugetlb : 1; /**< Indicates if we are using HugeTLB */ Eina_Bool faulty : 1; /**< Indicates if this region was not mapped correctly (i.e. the call to mmap(2) failed). */ +#ifdef _WIN32 + void *ret; /**< A pointer to the mapped region */ +#endif }; /** diff --git a/src/lib/eina/eina_file_win32.c b/src/lib/eina/eina_file_win32.c index ca8e78b83e..46449fdb57 100644 --- a/src/lib/eina/eina_file_win32.c +++ b/src/lib/eina/eina_file_win32.c @@ -900,7 +900,7 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, if (offset + length > file->length) return NULL; - if (offset == 0 && length == file->length) + if (offset == 0UL && length == file->length) return eina_file_map_all(file, rule); if (file->virtual) @@ -914,40 +914,56 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, map = eina_hash_find(file->map, &key); if (!map) { + SYSTEM_INFO si; HANDLE fm; + __int64 map_size; + DWORD view_offset; + DWORD view_length; + DWORD granularity; + map = malloc(sizeof (Eina_File_Map)); if (!map) - { - eina_lock_release(&file->lock); - return NULL; - } + goto on_error; - /* the length parameter is unsigned long, that is a DWORD */ - /* so the max size high parameter of CreateFileMapping is 0 */ + /* + * the size of the mapping object is the offset plus the length, + * which might be greater than a DWORD + */ + map_size = (__int64)offset + (__int64)length; fm = CreateFileMapping(file->handle, NULL, PAGE_READONLY, - 0, (DWORD)length, NULL); + (DWORD)((map_size >> 32) & 0x00000000ffffffffULL), + (DWORD)(map_size & 0x00000000ffffffffULL), + NULL); if (!fm) - return NULL; + goto on_error; + /* + * get the system allocation granularity as the + * offset passed to MapViewOfFile() must be a + * multiple of this granularity + */ + GetSystemInfo(&si); + granularity = si.dwAllocationGranularity; + + /* + * view_offset is the greatest multiple of granularity, less or equal + * than offset (and can be stored in a DWORD) + */ + view_offset = (offset / granularity) * granularity; + view_length = (offset - view_offset) + length; map->map = MapViewOfFile(fm, FILE_MAP_READ, - offset & 0xffff0000, - offset & 0x0000ffff, - length); + 0, + view_offset, + view_length); CloseHandle(fm); if (!map->map) - map->map = MAP_FAILED; + goto on_error; + map->ret = (unsigned char *)map->map + (offset - view_offset); map->offset = offset; map->length = length; map->refcount = 0; - if (map->map == MAP_FAILED) - { - free(map); - eina_lock_release(&file->lock); - return NULL; - } - eina_hash_add(file->map, &key, map); eina_hash_direct_add(file->rmap, map->map, map); } @@ -956,7 +972,13 @@ eina_file_map_new(Eina_File *file, Eina_File_Populate rule, eina_lock_release(&file->lock); - return map->map; + return map->ret; + + on_error: + free(map); + eina_lock_release(&file->lock); + + return NULL; } EAPI void