[Bug 8229] New: callbacks from win16 extended program that allocate
linear memory screw up pointers
wine-bugs at winehq.org
Mon Apr 30 00:59:58 CDT 2007
Summary: callbacks from win16 extended program that allocate
linear memory screw up pointers
AssignedTo: wine-bugs at winehq.org
ReportedBy: lupien at physique.usherbrooke.ca
I have a 32-bit extended windows 3.x program. It was produced with the watcom
compiler and extender. It fails with unhandled memory exceptions around callback
I explored the problem and I figured out the reason. In some callbacks the
program request more memory which the extender transforms into a call to dpmi
function 0x503 (Resize memory block, in dlls/winedos/int31.c). The work is
actually done in DPMI_xrealloc which currently creates a new memory area, copies
and then erases the old area (it does not grow the old area). This is a possible
result of the DPMI call and the extender seems to handle it properly (it remaps
all the segments it is using). But the problem happens in wine. Some pointers
are not remapped which end up producing an unhandled memory exceptions.
in dlls/user32/winproc.c, function WINPROC_CallProc16To32A we have
MDICREATESTRUCT16 *cs16 = MapSL(lParam);
MDICREATESTRUCT16to32A( cs16, &cs );
ret = callback( hwnd32, msg, wParam, (LPARAM)&cs, result, arg );
MDICREATESTRUCT32Ato16( &cs, cs16 );
cs16 is mapped to the 16 bit far pointer into the program data, then its data is
transfered into cs by MDICREATESTRUCT16to32A(). Then the callback routine is
called which will produce a memory reallocation. After the callback the
MDICREATESTRUCT32Ato16() function fails because cs16 now points to nowhere, the
data has been moved. This can be fixed here by adding
between the callback and MDICREATESTRUCT32Ato16() (Assuming the extender as
properly modified the segment which seems to be the case for me).
I believe this problem exist in many places in the code. Another place that gave
me a crash was in DispatchMessage16 of dlls/user32/msg16.c
where the problem occurs in the SPY_ExitMessage() function after the
CallWindowProc16() call. The bad pointer here is msg which is implicitely
converted by relay_call_from_16_no_debug() in dlls/kernel32/relay16.c.
Because the change is implicit, the only fix I could simply implement was to
make a local copy of the msg structure and use that for SPY_ExitMessage().
I will attach the patches that fix the problems for me, but they are only
partial solutions. I am pretty sure the problem exist in many other places in
the code (use of MapSL pointers around callbacks to client code).
For global solutions they are a few possibilites:
1) Do like I did but everywhere. So find all problem area and make sure the
pointers are updated and check for futur problems.
2) Change the DPMI_xrealloc so that it actually grows the memory instead of
moving it. This would possibly fix most problems but there are probably
circumstances (or other windows extenders) that would make that impossible (if
the memory allocations prevents the growing). For my extender there seems to be
only one allocation followed by many realloc (at least for my particular
3) Find a more general solution, maybe where the MapSL would keep track of all
the current pointers so that the realloc could fix those pointers automatically.
Obviously this is more complicated, and possibly impossible (need to keep track
of copies of those pointers also) but it would certainly fix all possible problems.
This problem was difficult to figure out. It probably has affected many other
programs and will keep being a strange problem until a global solution is
implemented. At least it should be in a warning in developper/debugging guides.
I am sorry but I don't have the time or complete enough knowledge of wine to
write the global fix.
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
More information about the wine-bugs