PRB: WinExec() Fails Due to Memory Not De-allocated (126710)



The information in this article applies to:

  • Microsoft Win32s 1.3c
  • Microsoft Win32s 1.15
  • Microsoft Win32s 1.2
  • Microsoft Win32s 1.25
  • Microsoft Win32s 1.3
  • Microsoft Win32s 1.30a

This article was previously published under Q126710

SYMPTOMS

Under Win32s version 1.15, when a Win32-based application spawns a 16-bit application several times using WinExec(), after a few successful spawns, WinExec() fails.

Each time WinExec() is called to start a 16-bit application, Win32s allocates a fixed and page-locked block. The owner of this block is the Win32-based application. The memory is not de-allocated when the 16-bit application is terminated, only when the 32-bit application is terminated.

CAUSE

This is actually a bug in Windows version 3.1. The 32-bit WinExec() calls the 16-bit LoadModule(). Win32s passes the environment of the calling process to LoadModule(). Then the Windows 3.1 LoadModule() allocates a buffer for the environment, copies this environment to the buffer, and passes this buffer to the child process. The problem is that the owner of the new allocated buffer is the parent, so the memory is freed when the parent exits. There is no code for otherwise freeing the memory. This bug also affects 16-bit Windows-based applications if LoadModule() is called with an environment selector that is not NULL.

In a related problem, when the parent terminates, the child's environment becomes invalid. This may cause a general protection (GP) fault.

RESOLUTION

To work around the problem, you can call the Windows version 3.1 WinExec() through the Universal Thunk. However, the parent will not be able to modify the child's environment.

In Win32s version 1.2x and later, this problem exists only if you start 16- bit application using CreateProcess() or LoadModule() and pass it explicit environment strings. In this case, you will encounter the Windows version 3.1 bug. If you do not pass an explicit environment, the environment passed to the 16-bit application is NULL. This resolves the problems mentioned in the Symptoms and Cause sections of this article.

MORE INFORMATION

With the changes in Win32s version 1.2x, if the calling application modifies the environment, the child process will not get the modified environment of the parent. It will get the global MS-DOS environment. This is also true for WinExec().

If you need to pass a modified environment, call LoadModule() or CreateProcess() with the environment set to what GetEnvironmentStrings() returns. Be aware that this will cause a memory leak. In addition, if the parent terminates before the child, the child's environment will become invalid.

Modification Type:MajorLast Reviewed:3/15/2004
Keywords:KB126710