[PATCH 0/2] MR10038: comctl32: Fix the bug when the cInitial is too large which lead to CreateDIBSection fails.
Logs: When CreateDIBSection does not return a valid hbitmap, the source image is lost that only masked icon is shown in imagelist. Signed-off-by: Kun Yang <yangkun@uniontech.com> -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038
From: Kun Yang <yangkun@uniontech.com> Logs: When CreateDIBSection does not return a valid hbitmap, the source image is lost that only masked icon is shown in imagelist. Signed-off-by: Kun Yang <yangkun@uniontech.com> --- dlls/comctl32/imagelist.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c index 93c502ec0bd..443078600e4 100644 --- a/dlls/comctl32/imagelist.c +++ b/dlls/comctl32/imagelist.c @@ -3088,6 +3088,15 @@ static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count) } } hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0); + if(!hbmNewBitmap) + { + UINT newImageCount = 1; + //if CreateDIBSection failed, allocate for 1 image only. + bmi->bmiHeader.biHeight = newImageCount * himl->cy; + hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0); + //the max image count is set to 2, expand when exceeded. + himl->cMaxImage = newImageCount + 1; + } } else /*if (ilc == ILC_COLORDDB)*/ { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10038
From: Kun Yang <yangkun@uniontech.com> This reverts commit 257b697508704131531e4365ff21ffe48fc28a09 --- dlls/kernelbase/file.c | 6 ++---- dlls/mountmgr.sys/unixlib.c | 36 ---------------------------------- dlls/ntdll/unix/file.c | 35 --------------------------------- dlls/ntdll/unix/virtual.c | 21 +++++++++----------- dlls/win32u/main.c | 2 +- dlls/win32u/syscall.c | 7 ++++++- dlls/winex11.drv/dllmain.c | 3 ++- dlls/winex11.drv/x11drv_main.c | 16 ++++++++++++++- dlls/wow64/virtual.c | 8 +------- include/wine/unixlib.h | 1 - 10 files changed, 36 insertions(+), 99 deletions(-) diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 7c079260af9..e271b03de1f 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -3620,7 +3620,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH ReadFile( HANDLE file, LPVOID buffer, DWORD count, status = io_status->Status; } - if (result && (!overlapped || !status)) *result = io_status->Information; + if (result) *result = overlapped && status ? 0 : io_status->Information; if (status == STATUS_END_OF_FILE) { @@ -4013,8 +4013,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteFile( HANDLE file, LPCVOID buffer, DWORD coun else piosb->Information = 0; piosb->Status = STATUS_PENDING; - if (result) *result = 0; - status = NtWriteFile( file, event, NULL, cvalue, piosb, buffer, count, poffset, NULL ); if (status == STATUS_PENDING && !overlapped) @@ -4023,7 +4021,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteFile( HANDLE file, LPCVOID buffer, DWORD coun status = piosb->Status; } - if (result && (!overlapped || !status)) *result = piosb->Information; + if (result) *result = overlapped && status ? 0 : piosb->Information; if (status && status != STATUS_TIMEOUT) { diff --git a/dlls/mountmgr.sys/unixlib.c b/dlls/mountmgr.sys/unixlib.c index 2a5fd272db6..bcc36383834 100644 --- a/dlls/mountmgr.sys/unixlib.c +++ b/dlls/mountmgr.sys/unixlib.c @@ -36,10 +36,6 @@ #ifdef HAVE_SYS_STATVFS_H # include <sys/statvfs.h> #endif -#ifdef __APPLE__ -# include <CoreFoundation/CoreFoundation.h> -# include <sys/param.h> -#endif #include <unistd.h> #include "unixlib.h" @@ -315,28 +311,6 @@ static NTSTATUS set_dosdev_symlink( void *args ) return status; } -#ifdef __APPLE__ -static LONGLONG get_free_bytes_for_important_data(int fd) -{ - CFURLRef url = NULL; - CFNumberRef num = NULL; - char *path = NULL; - LONGLONG space = -1; - - if (!(path = malloc( MAXPATHLEN ))) goto done; - if (fcntl( fd, F_GETPATH, path ) == -1) goto done; - if (!(url = CFURLCreateFromFileSystemRepresentation( NULL, (UInt8 *)path, strlen( path ), false ))) goto done; - if (!CFURLCopyResourcePropertyForKey( url, kCFURLVolumeAvailableCapacityForImportantUsageKey, &num, NULL )) goto done; - CFNumberGetValue( num, kCFNumberLongLongType, &space ); - -done: - free( path ); - if (url) CFRelease( url ); - if (num) CFRelease( num ); - return space; -} -#endif - static NTSTATUS get_volume_size_info( void *args ) { const struct get_volume_size_info_params *params = args; @@ -354,10 +328,6 @@ static NTSTATUS get_volume_size_info( void *args ) struct statfs stfs; #endif -#ifdef __APPLE__ - LONGLONG important_free_bytes; -#endif - if (!unix_mount) return STATUS_NO_SUCH_DEVICE; if (unix_mount[0] != '/') @@ -395,12 +365,6 @@ static NTSTATUS get_volume_size_info( void *args ) } bsize = stfs.f_bsize; #endif - -#ifdef __APPLE__ - important_free_bytes = get_free_bytes_for_important_data( fd ); - if (important_free_bytes != -1) stfs.f_bavail = stfs.f_bfree = important_free_bytes / bsize; -#endif - if (bsize == 2048) /* assume CD-ROM */ { info->bytes_per_sector = 2048; diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 4c36bec9e7c..488de37b508 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -103,9 +103,6 @@ #undef XATTR_ADDITIONAL_OPTIONS #include <sys/extattr.h> #endif -#ifdef __APPLE__ -#include <CoreFoundation/CoreFoundation.h> -#endif #include <time.h> #include <unistd.h> @@ -2176,28 +2173,6 @@ static NTSTATUS server_get_name_info( HANDLE handle, FILE_NAME_INFORMATION *info } -#ifdef __APPLE__ -static LONGLONG get_free_bytes_for_important_data(int fd) -{ - CFURLRef url = NULL; - CFNumberRef num = NULL; - char *path = NULL; - LONGLONG space = -1; - - if (!(path = malloc( MAXPATHLEN ))) goto done; - if (fcntl( fd, F_GETPATH, path ) == -1) goto done; - if (!(url = CFURLCreateFromFileSystemRepresentation( NULL, (UInt8 *)path, strlen(path), false ))) goto done; - if (!CFURLCopyResourcePropertyForKey( url, kCFURLVolumeAvailableCapacityForImportantUsageKey, &num, NULL )) goto done; - CFNumberGetValue( num, kCFNumberLongLongType, &space ); - -done: - free( path ); - if (url) CFRelease( url ); - if (num) CFRelease( num ); - return space; -} -#endif - static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) { struct stat st; ULONGLONG bsize; @@ -2208,10 +2183,6 @@ static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) struct statfs stfs; #endif -#ifdef __APPLE__ - LONGLONG important_free_bytes; -#endif - if (fstat( fd, &st ) < 0) return errno_to_status( errno ); if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) return STATUS_INVALID_DEVICE_REQUEST; @@ -2223,12 +2194,6 @@ static NTSTATUS get_full_size_info(int fd, FILE_FS_FULL_SIZE_INFORMATION *info) if (fstatfs( fd, &stfs ) < 0) return errno_to_status( errno ); bsize = stfs.f_bsize; #endif - -#ifdef __APPLE__ - important_free_bytes = get_free_bytes_for_important_data( fd ); - if (important_free_bytes != -1) stfs.f_bavail = stfs.f_bfree = important_free_bytes / bsize; -#endif - if (bsize == 2048) /* assume CD-ROM */ { info->BytesPerSector = 2048; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 7c2b95f0427..222ac2e7733 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -840,11 +840,12 @@ void *get_builtin_so_handle( void *module ) /*********************************************************************** * get_unixlib_funcs */ -static NTSTATUS get_unixlib_funcs( void *so_handle, BOOL wow, const void **funcs, NTSTATUS (**entry)(void) ) +static NTSTATUS get_unixlib_funcs( void *so_handle, BOOL wow, const void **funcs ) { - *funcs = dlsym( so_handle, wow ? "__wine_unix_call_wow64_funcs" : "__wine_unix_call_funcs" ); - *entry = dlsym( so_handle, "__wine_unix_lib_init" ); - return *funcs || *entry ? STATUS_SUCCESS : STATUS_ENTRYPOINT_NOT_FOUND; + const char *name = wow ? "__wine_unix_call_wow64_funcs" : "__wine_unix_call_funcs"; + + *funcs = dlsym( so_handle, name ); + return *funcs ? STATUS_SUCCESS : STATUS_ENTRYPOINT_NOT_FOUND; } @@ -853,7 +854,6 @@ static NTSTATUS get_unixlib_funcs( void *so_handle, BOOL wow, const void **funcs */ static NTSTATUS load_builtin_unixlib( void *module, BOOL wow, const void **funcs ) { - NTSTATUS (*entry)(void) = NULL; sigset_t sigset; NTSTATUS status = STATUS_DLL_NOT_FOUND; struct builtin_module *builtin; @@ -867,10 +867,9 @@ static NTSTATUS load_builtin_unixlib( void *module, BOOL wow, const void **funcs if (!builtin->unix_handle) WARN_(module)( "failed to load %s: %s\n", debugstr_a(builtin->unix_path), dlerror() ); } - if (builtin->unix_handle) status = get_unixlib_funcs( builtin->unix_handle, wow, funcs, &entry ); + if (builtin->unix_handle) status = get_unixlib_funcs( builtin->unix_handle, wow, funcs ); } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); - if (!status && entry) status = entry(); return status; } @@ -6143,17 +6142,15 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr, { UINT64 res[2]; const UNICODE_STRING *name = addr; - NTSTATUS (*entry)(void); const void *funcs; void *handle; if ((status = load_unixlib_by_name( name, &handle ))) return status; res[0] = (UINT_PTR)handle; - if (!(status = get_unixlib_funcs( handle, info_class == MemoryWineLoadUnixLibByNameWow64, - &funcs, &entry ))) + if (len >= sizeof(res)) { - res[1] = (UINT_PTR)funcs; - if (entry) status = entry(); + if (!(status = get_unixlib_funcs( handle, info_class == MemoryWineLoadUnixLibByNameWow64, &funcs ))) + res[1] = (UINT_PTR)funcs; } if (status) dlclose( handle ); else memcpy( buffer, res, min( len, sizeof(res) )); diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 5593eda9aab..c0482ba059f 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -2573,7 +2573,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, void *reserved ) LdrGetDllHandle( NULL, 0, &ntdll_name, &ntdll ); dispatcher_ptr = RtlFindExportedRoutineByName( ntdll, "__wine_syscall_dispatcher" ); __wine_syscall_dispatcher = *dispatcher_ptr; - __wine_init_unix_call(); + if (!__wine_init_unix_call()) WINE_UNIX_CALL( 0, NULL ); break; } return TRUE; diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index aac3d85296c..4bbd8c6f4ec 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -169,7 +169,7 @@ static const char *usercall_names[NtUserCallCount] = #undef USER32_CALLBACK_ENTRY }; -NTSTATUS __wine_unix_lib_init(void) +static NTSTATUS init( void *args ) { #ifdef _WIN64 if (NtCurrentTeb()->WowTebOffset) @@ -184,3 +184,8 @@ NTSTATUS __wine_unix_lib_init(void) ntdll_add_syscall_debug_info( 1, syscall_names, usercall_names ); return STATUS_SUCCESS; } + +const unixlib_entry_t __wine_unix_call_funcs[] = +{ + init, +}; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 1a75e344722..ae7084dd6c3 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -28,5 +28,6 @@ BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, void *reserved ) if (reason != DLL_PROCESS_ATTACH) return TRUE; DisableThreadLibraryCalls( instance ); - return !__wine_init_unix_call(); + if (__wine_init_unix_call()) return FALSE; + return !WINE_UNIX_CALL( 0, NULL ); } diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index e53aebc3739..0b8eedadd98 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -622,7 +622,7 @@ static void init_visuals( Display *display, int screen ) /*********************************************************************** * X11DRV process initialisation routine */ -NTSTATUS __wine_unix_lib_init(void) +static NTSTATUS x11drv_init( void *arg ) { Display *display; void *libx11 = dlopen( SONAME_LIBX11, RTLD_NOW|RTLD_GLOBAL ); @@ -804,3 +804,17 @@ BOOL X11DRV_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, } return FALSE; /* let user32 handle it */ } + +const unixlib_entry_t __wine_unix_call_funcs[] = +{ + x11drv_init, +}; + +#ifdef _WIN64 + +const unixlib_entry_t __wine_unix_call_wow64_funcs[] = +{ + x11drv_init, +}; + +#endif /* _WIN64 */ diff --git a/dlls/wow64/virtual.c b/dlls/wow64/virtual.c index 5f969105356..649feb0c5d8 100644 --- a/dlls/wow64/virtual.c +++ b/dlls/wow64/virtual.c @@ -699,14 +699,8 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args ) status = NtQueryVirtualMemory( handle, addr, MemoryWineLoadUnixLibWow64, ptr, len, &res_len ); break; case MemoryWineLoadUnixLibByName: - { - UNICODE_STRING32 *str32 = addr; - UNICODE_STRING str; - - status = NtQueryVirtualMemory( handle, unicode_str_32to64( &str, str32 ), - MemoryWineLoadUnixLibByNameWow64, ptr, len, &res_len ); + status = NtQueryVirtualMemory( handle, addr, MemoryWineLoadUnixLibByNameWow64, ptr, len, &res_len ); break; - } case MemoryWineUnloadUnixLib: status = NtQueryVirtualMemory( handle, addr, class, ptr, len, &res_len ); break; diff --git a/include/wine/unixlib.h b/include/wine/unixlib.h index b0fd9b2604d..77f9c7cb374 100644 --- a/include/wine/unixlib.h +++ b/include/wine/unixlib.h @@ -34,7 +34,6 @@ typedef UINT64 unixlib_module_t; typedef NTSTATUS (*unixlib_entry_t)( void *args ); -extern DECLSPEC_EXPORT NTSTATUS __wine_unix_lib_init(void); extern DECLSPEC_EXPORT const unixlib_entry_t __wine_unix_call_funcs[]; extern DECLSPEC_EXPORT const unixlib_entry_t __wine_unix_call_wow64_funcs[]; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10038
Please add a test. And remove the last two unrelated patches. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038#note_128938
On Fri Feb 6 05:04:26 2026 +0000, Zhiyi Zhang wrote:
Please add a test. And remove the last two unrelated patches. I'm sorry the origin merge request is !10034 , I have my test in that issue. I don't know how this request is generated.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038#note_128939
This merge request was closed by Kun Yang. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038
On Fri Feb 6 05:04:26 2026 +0000, Kun Yang wrote:
I'm sorry the origin merge request is !10034 , I have my test in that issue. I don't know how this request is generated. Maybe Windows has checks for an extremely large initial image count, like 0xc0c0c0. You can add the tests to the test suites for Wine. Please see wine/dlls/comctl32/tests/imagelist.c.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038#note_128942
On Fri Feb 6 06:11:44 2026 +0000, Zhiyi Zhang wrote:
Maybe Windows has checks for an extremely large initial image count, like 0xc0c0c0. You can add the tests to the test suites for Wine. Please see wine/dlls/comctl32/tests/imagelist.c. I have test for this, can you have a look at !10039 , thanks.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10038#note_128944
participants (3)
-
Kun Yang -
Kun Yang (@yangkun) -
Zhiyi Zhang (@zhiyi)