From: Alex Henrie <alexhenrie24@gmail.com> If a resource is marked DISCARDABLE, it is not actually freed when its refcount reaches 0. In theory the resource's memory is freed when the system is low on memory, but its global handle remains valid to allow the resource to be resurrected with the same handle later. In practice, 16-bit programs can't run out of memory on modern hardware, and the game Tetris Jr. depends on its discardable resources never being discarded. See https://devblogs.microsoft.com/oldnewthing/20040202-00/?p=40783 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=23364 --- dlls/krnl386.exe16/resource.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/dlls/krnl386.exe16/resource.c b/dlls/krnl386.exe16/resource.c index bcdb01a3b30..e833297ab4c 100644 --- a/dlls/krnl386.exe16/resource.c +++ b/dlls/krnl386.exe16/resource.c @@ -1023,6 +1023,8 @@ HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc ) if (pNameInfo->handle && !(GlobalFlags16(pNameInfo->handle) & GMEM_DISCARDED)) { pNameInfo->usage++; + GlobalReAlloc16( pNameInfo->handle, 0, + (GlobalFlags16( pNameInfo->handle ) & ~GMEM_DISCARDABLE) | GMEM_MODIFY ); TRACE(" Already loaded, new count=%d\n", pNameInfo->usage ); } else @@ -1127,9 +1129,17 @@ BOOL16 WINAPI FreeResource16( HGLOBAL16 handle ) if (pNameInfo->usage > 0) pNameInfo->usage--; if (pNameInfo->usage == 0) { - GlobalFree16( pNameInfo->handle ); - pNameInfo->handle = 0; - pNameInfo->flags &= ~NE_SEGFLAGS_LOADED; + if (pNameInfo->flags & NE_SEGFLAGS_DISCARDABLE) + { + GlobalReAlloc16( pNameInfo->handle, 0, + GlobalFlags16( pNameInfo->handle ) | GMEM_DISCARDABLE | GMEM_MODIFY ); + } + else + { + GlobalFree16( pNameInfo->handle ); + pNameInfo->handle = 0; + pNameInfo->flags &= ~NE_SEGFLAGS_LOADED; + } } return FALSE; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11742