WIN_WRAP

Synopsis:

A Windows 3.1 program launcher that prevents the client app from 
taking valuable 'low memory'. 

Released to the public domain. (Except for the BELOW1M.EXE file)

Short README:
------------
Have you ever run into the situation where you are trying to 
launch a Windows app, and nothing happens? Perhaps you're out
of memory?

You know you have gobs of virtual memory left, and the Program
Manager AboutBox says that you've got 60% resources left. What gives?

It's possible that you have run into a little known Windows3.1
roadblock. Perhaps you're out of 'low memory'. This is the precious
memory below the 1 meg line. For an excellent discussion of this
problem, see the article by Matt Pietrek in the Oct/93 issue of
Microsoft Systems Journal.

If this is your problem, then a previous application has been loaded
which locked down some low memory. All apps require at least 512 bytes,
but some will take much more if they can. If the app (or apps) have 
taken all the low memory, the Windows will refuse to launch anymore
apps (since it needs the 512 bytes), and will NOT give the user
any indication of what happened (or rather, what didn't happen).

If you can identify the offending app (or apps), then you can use
the WIN_WRAP program to launch it. WIN_WRAP will try to force
your app to load itself high in memory.

What WIN_WRAP does is: take ALL of the low memory; give back 1k;
launch your app; release back all of the rest of the memory to the system.

If your app requires locked memory, it will get it, but ABOVE the
1 meg line. When WIN_WRAP terminates (immediately after the client
app is launched), the low memory is freed up, so that lots of other
apps can run. 

Since WIN_WRAP removes itself almost immediately, you can use it
many times in the same session.

Usage:
------
Instead of running 
	RECORDER.EXE textfile.txt
you can run
	WIN_WRAP RECORDER.EXE textfile.txt

In the former case, the RECORDER.EXE program will take 3 segments from the 
low memory area:
	the TDB (task database)
	a code segment (about 11k)
	a data segment (about 2.5k)
In the latter case, the RECORDER.EXE program executes properly, but only
takes 1 segment from the low memory area: the TDB. The other two segments
are located in high memory, where there's lots of space.

You can put any valid command line after the WIN_WRAP command. These 
compound commands may be put in your Program Manager icons on the 
'Command Line' entry. (Hit Alt-Enter to view the icon-properties).

If you want WIN_WRAP to operate on programs in your Startup group, just
modify the CommandLine entries in the Startup group. I haven't figured 
out how to use WIN_WRAP with the 'load=' and 'run=' options in the WIN.INI.

Long README:
-----------

Many applications use Windows functions that require 'callbacks'.
A 'callback' is the way that an application can register
itself for notification of system activity. The kind of
'callback's that I am referring to here are interrupt service code
segments, such as netbios client code, IPX client code, TCP/IP
client code.
	
This code MUST be in memory at all times. The proper way to ensure
that it is in memory is to lock it in place. There are two ways 
to do that.

Method 1: Microsoft suggests that this kind of code be written in 
a .DLL, and that the code+data segment be marked as FIXED. At .DLL load
time, Windows will load this code+data 'as low as possible' in the 
Windows memory map (the Windows VM, actually). In a healthy machine,
this will be below the 1meg line. The segments are locked in place and
PageLocked.

Method 2: If the code+data to be executed resides in an .EXE file, then
the segments will be loaded high in the Windows memory map, and left
MOVEABLE. The programmer can, however, call GlobalPageLock() to lock
the memory in place. It appears, however, that just before Windows
locks down the memory, it moves it down into low Windows memory, and,
as above, in a healthy machine, this will be below the 1meg line.

The memory below the 1meg line is used for many things:
	-DOS for this VM
	-TSR's and device drivers for this VM
	-all GlobalDosAllocs()
	-DPMI buffers for this VM
	-a TDB (Task Data Base) segment, per app
The TDB must be located there, because it has to be accessed by
the Windows app (using a selector) and by DOS (using the equivalent
segment register). Windows will refuse to launch an app if it cannot
get the TDB into low memory.

Many apps require locked and PageLocked segments so that they can present
Windows with callback services.

You can see that both Method 1 and 2 will push the PageLocked memory as low
as possible, usually into this 'below 1meg' memory.

Most often, these segments (code+data) do not need to be in the first 
meg of ram; i.e. they do not need to be accessed from real mode. 

The application will allocate these segments using GlobalAlloc()+GlobalPageLock(). 
These segments are the ones that WIN_WRAP will push up high.

Sometimes an app WILL require low memory. It will request it from the system
by calling GlobalDosAlloc(). If you try to launch one of these apps with 
WIN_WRAP, the GlobalDosAlloc() will fail, and the program will not launch.
These apps are not appropriate for WIN_WRAP.

The type of applications that I have used WIN_WRAP with are netbios
aware apps, TCP/IP client apps and .DLL's and IPX apps. Netbios
buffers may be located above the 1meg line, and IPX buffers can
be as well (if IPX is more recent than 09/92). 

To help you visualize the activity of WIN_WRAP, I have included
the BELOW1M application written by Matt Pietrek. This program is
NOT public domain; it is copyright Matt Pietrek - 1993. 

The operation of WIN_WRAP is not guaranteed. Use it at your own risk.

WIN_WRAP is released to the public domain. As usual, I ask the courtesy
of feedback if you enhance this tool.

Pat Beirne
76475,3640
patb@corel.ca
