[PATCH] Fix handling of zero_bits argument in NtAllocateVirtualMemory

Las at protonmail.ch Las at protonmail.ch
Fri Feb 15 08:24:42 CST 2019

Patch attached. This is my first contribution to wine, and I have checked through the wiki for what I should do, and have attempted to fulfill all criteria.

Commit message from patch:

Before, Wine would (very incorrectly) use the argument to specify
how many *low-order* address bits should be 0, when in fact,
in Windows it's used to specify how many *high-order* address bits
should be zero!

The functionality is taken from the documentation for NtAllocateVirtualMemory:
The number of high-order address bits that must be zero in the base address
of the section view. Used only when the operating system determines where
to allocate the region, as when BaseAddress is NULL. Note that when
ZeroBits is larger than 32, it becomes a bitmask.

and NtMapViewOfSection:
Specifies the number of high-order address bits that must be zero in the
base address of the section view. The value of this parameter must be less
than 21 and is used only if BaseAddress is NULL—in other words, when the
caller allows the system to determine where to allocate the view.

and from documentation for LuaJIT's allocator:
/* Number of top bits of the lower 32 bits of an address that must be zero.
** Apparently 0 gives us full 64 bit addresses and 1 gives us the lower 2GB.

Thus the interpretation done here is:
If zero_bits is 0, use the full address space.
If zero_bits is over 20, err (12-bit pointers are the smallest allowed).
Otherwise only the lower (32-zero_bits) bits should be used.

A lot of internal Wine functionality unfortunately depends on the old
Wine behavior, but thankfully, all of the uses seem to be redundant,
as no function requested an alignment higher than the minimum!
It may however be that I have not fully understood the code,
as it is not always clear what alignment is requested.

In addition, to implement this odd Windows API, Wine somehow has to
mmap an address below the maximum, which is not possible efficiently
on POSIX systems compared to the Windows API. Linux has the MAP_32BIT
flag, but it restricts the address space to just 1 GiB, which is not
enough. For that reason, the implementation of this API in Wine
uses pseudorandom heuristics ripped from the LuaJIT project (which
also seems to be the only project to use this Windows API) to achieve
this. It is not optimal, but it works. A proper implementation would
require extensions to the mmap API.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20190215/e1c81cf4/attachment.html>

More information about the wine-devel mailing list