       Copyright (C) 1995 MetaWare Incorporated.  All Rights Reserved.

            MetaWare 32-Bit Windows Application Development Kit
                                January 1995

------------------------------------------------------------------------------
NOTE:  Important for Distribution of Applications

       The dynamic link library MWSUPDLL.DLL is called by all applications
       developed with the ADK.  If you develop programs for resale and
       distribution, you must include MWSUPDLL.DLL with each of the products
       you distribute.  There is NO royalty attached to using this file.
------------------------------------------------------------------------------


Table of Contents
-----------------
  1. Introduction
  2. Installation and Set-Up
  3. 32-Bit DLLs
  4. Call16() Function
  5. Large Bitmap Support
  6. COMMDLG Functions
  7. The DEVMOD Structure
  8. Debugging in Windows -- MDBW
  9. Make Utility
 10. Required Source Code Changes
 11. Error Message "Cannot find mwsupdll.dll"
 12. Changes to the High C/C++ Windows 32-Bit Application Developer's Guide
 13. Windows Problems
 14. Known Problems
 15. Windows Applications and OS/2
 16. Frequently Asked Questions
 17. Trouble-Shooting Tip


1. Introduction
---------------

With the MetaWare Windows Application Development Kit (ADK), plus a High C/C++
compiler and Microsoft Windows, you can develop and run 32-bit applications 
in the Windows 386 enhanced-mode environment.

We ship the Microsoft Resource Compiler with the ADK so you can develop many 
32-bit Windows applications without Microsoft Windows SDK.


2. Installation and Set-Up
--------------------------

The MetaWare Windows ADK is installed on top of your High C/C++ compiler
installation.  The resulting installed software can generate both 32-bit
Windows applications and non-Windows extended-DOS applications.

WARNING:  If you are using Phar Lap 386|DOS-Extender 5.0 or later, you MUST 
open the hc386set.cnf file and uncomment the line STUB_LOADER_USED=yes.


3. 32-Bit DLLs
--------------

The MetaWare ADK supports creating 32-bit dynamic link libraries (DLLs).  See
the ...\win\sdk\select directory for example source code.  A DLL is compiled
separately from your main Windows application, and is not linked directly with
your program until execution.  You can use Windows function calls to load the
DLL into memory, and obtain the address of a function in the library that you
want to call.  See the Windows Application Developer's Guide for more
information.


4. Call16() Function
--------------------

The MetaWare ADK lets you load 16-bit dynamic link libraries (DLLs).  After a 
DLL is loaded, you can obtain the address of a function in the DLL, and call 
it using the ADK's Call16() function.


5. Large Bitmap Support
-----------------------

The MetaWare ADK supports large (>64k) bitmaps.  To use large bitmaps, 
you must store the bitmap itself in memory allocated from Windows via 
GlobalAlloc().  Then use the Windows API functions normally, passing in 
the pointer retrieved by GlobalLock(); your program will function correctly.

There is an example program called BIGBIT available from MetaWare that
demonstrates using large bitmaps.  It asks the user for the name of a
bitmap, using the GetOPenFileName Common Dialog, then displays the
bitmap, tiled, in the client area of its window.  To get a copy of this
program, contact MetaWare Technical Support and ask for BIGBIT.ZIP.


6. COMMDLG Functions
--------------------

This version of the MetaWare ADK supports the COMMDLG functions.  These are:

     ChooseColor()
     ChooseFont()
     FindText()
     GetFileTitle()
     GetOpenFileName()
     GetSaveFileName()
     PrintDlg()
     ReplaceText()
     CommDlgExtendedError()


7. The DEVMOD Structure
-----------------------

Currently, no intelligent "thunking" of the DEVMODE structure is done for 
PRINTDLG's hDevMode member.  If you use this member, you yourself must 
ensure that the structure you pass in can map to its 16-bit equivalent.  
Use this structure to map the members properly:

   typedef struct tagDEVMODE32 {
      char           dmDeviceName[CCHDEVICENAME];
      unsigned short dmSpecVersion;
      unsigned short dmDriverVersion;
      unsigned short dmSize;
      unsigned short dmDriverExtra;
      DWORD          dmFields;
      short          dmOrientation;
      short          dmPaperSize;
      short          dmPaperLength;
      short          dmPaperWidth;
      short          dmScale;
      short          dmCopies;
      short          dmDefaultSource;
      short          dmPrintQuality;
      short          dmColor;
      short          dmDuplex;
      short          dmYResolution;
      short          dmTTOption;
      } DEVMODE32;


8. Debugging in Windows -- MDBW
-------------------------------

The MetaWare ADK includes a Windows version of the MetaWare 32-Bit Source-Level
Debugger, MDBW.  MDBW is designed to allow source-level debugging of the 
32-bit protected-mode programs generated by the Windows ADK.  MDBW is hosted 
on Windows to allow you to debug your applications within the Windows
environment.  MDBW includes the files MWDEBUG.DLL and VMW32D.386.

*  Configuring Windows for Debugging:  To use the debugger, you must edit 
   your WINDOWS\SYSTEM.INI file to include the following line:

      [386Enh]
      DEVICE=vmw32d.386

*  Known problems with MDBW.

   - The RELOAD command does not work under Windows.

   - MDBW may be unstable if the application exits with an error.
     If you are unable to restart MDBW, exit out of Windows and
     restart.

   - DOS program SHARE.EXE may cause a program load to fail.

   - Multiple breakpoints at one address are not supported.

   - CALLSTACK cannot display register-based arguments.


9. Make Utility
---------------

The MetaWare make utility MWMAKE is a protected-mode make based on popular
UNIX versions of make.  It is provided to build the supplied Windows example 
programs.  It is not meant to be a true development tool.  

Currently, a bug exists in the handling of default rules.  The supplied 
makefiles avoid the use of default rules.


10. Required Source Code Changes
--------------------------------

The following source code changes are required when you port a 16-bit Windows
program to run under the MetaWare 32-bit Windows ADK.

* LocalLock() returns a far pointer.  Variables that are
  assigned the return value of a LocalLock() call should be
  declared as type "LPSTR" or "LP48STR" (or an equivalent type).

* Some Windows applications use the type "unsigned" in place of the type
  "WORD".  On a 32-bit platform, "unsigned" is four bytes long, while "WORD"
  is two bytes long.  Therefore, functions declared as, for example:

     LONG (FAR PASCAL *lpfnWndProc)(HWND, unsigned, WORD, LONG);

  should instead be declared as:

     LONG (FAR PASCAL *lpfnWndProc)(HWND, WORD, WORD, LONG);

* Occurrences of <TYPE> FAR * should be changed to LP<TYPE>.  For example, if
  your program declares a variable:

     CREATESTRUCT FAR * pCS;

  you should modify the declaration to be:

     LPCREATESTRUCT pCS;

  The LP types are declared in the Windows header files.

* The behavior of DebugBreak() has been modified slightly, to allow a program
  that contains calls to DebugBreak() to be run outside of a debugger.
  Normally, if a program calls DebugBreak() while being run outside of a
  debugger, the machine will hang.  We have modified DebugBreak() such that it
  will not execute an "int 3" instruction unless it is run under the MetaWare
  debugger for Windows, MDBW.  If you wish to have DebugBreak() execute an
  "int 3" instruction regardless of whether the program is running under the
  debugger, you have two options:

  1)  Set the environment variable DEBUGBREAK to any value.  If this variable
      is detected in the environment, all calls to DebugBreak() will execute
      an "int 3" instruction.

  2)  Replace calls to DebugBreak() with calls to _mwDebugBreak().
      _mwDebugBreak() will always execute an "int 3" instruction.

* The MakeProcInstance() function in the MetaWare ADK returns a 16:16 pointer.
  Usually this pointer is passed along to Windows.

     ...
     case IDM_ABOUT:
         lpProcAbout = MakeProcInstance(About, hInst);
         DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);
         FreeProcInstance(lpProcAbout);
         break;
     ...

  If you need to call this address directly, you must use the Call16()
  function, which allows your program to call 16:16 pointers-to-functions.
  For example:

     extern BOOL FAR PASCAL PrintDlgProc (HWND, WORD, WORD, DWORD);
     FARPROC     lpfnPrintDlgProc ;

     lpfnPrintDlgProc = MakeProcInstance (PrintDlgProc, hInst) ;
     ...
     #ifdef __HIGHC__
     Call16(lpfnPrintDlgProc,"wwwd", hWnd, message, wParam, lParam);
     #else
     lpfnPrintDlgProc(hWnd, message, wParam, lParam);
     #endif

  See the Application Developer's Guide for more information about Call16().

* Keep in mind that on a 32-bit platform an "int" is four bytes long, instead
  of two bytes as it is on a 16-bit platform.  If you make assumptions about
  the size of integer variables, you should use either "short" or "long"
  rather than "int".  If you notice problems in your program that seem to be
  caused by a variable having an unexpected value, be sure to check the size
  of that variable.  You may need to change "int" variables to be of type
  "short".


11. Error Message "Cannot find mwsupdll.dll"
-------------------------------------------

Whenever you run an ADK program, the DLL MWSUPDLL.DLL must be available to
Windows.  MWSUPDLL.DLL is a DLL that supports MWSUP.  It is sufficient for
MWSUPDLL.DLL to reside in the directory where your ADK program executes.
However, placing MWSUPDLL.DLL in your Windows SYSTEM directory insures that
Windows will always have access to the DLL.


12. Changes to the High C/C++ Windows 32-Bit Application Developer's Guide
--------------------------------------------------------------------------

- - - - - - - - - - -
Section 5.4, page 25:
- - - - - - - - - - -
* Add this paragraph before Step 1, at the top of the page:

    Because rc uses the environment variable INCLUDE (rather than IPATH)
    to search for include files, use the "set" command to add the required
    search path.  For example, 

      set INCLUDE=C:\HIGHC\WIN\INC;


- - - - - - - - - - -
Section 7.1, page 38:
- - - - - - - - - - -
* In the first paragraph, change the last sentence to read as follows:

    However, you should use GlobalAlloc() if you want your code to be ported
    easily between compilers.

* Before the Note, add this paragraph:

    When an ADK application calls LocalAlloc, it allocates memory from the
    data segment of the 16-bit portion of the supervisor.  Because the 
    supervisor uses almost all of its data segment itself, you can allocate
    very little memory with LocalAlloc (perhaps only a few hundred bytes).


- - - - - - - - - - -
Section A.2, page 66:
- - - - - - - - - - -
* Replace the Character / Type / Conversion table with the following table:

  Character | 32-Bit Side Expects:   | Converted to This, for 16-Bit Side:
  ==========+========================+=====================================
      b     |  4-byte integer        | 1 byte
      w     |  4-byte integer        | 2 bytes
      d     |  4-byte integer        | 4 bytes
      p     |  0:32 pointer (4 bytes)| DOS FAR (16:16) pointer (4 bytes)
      f     | 16:32 pointer (8 bytes)| DOS FAR (16:16) pointer (4 bytes)


13. Windows Problems
--------------------

If you experience a large number of "Unrecoverable Application Error" messages
when running Windows programs, check the following in your CONFIG.SYS file:

*  Set FILES to at least 30; preferably 40.

*  Set your environment to at least 1024 bytes, preferably 2048; with the line:

      SHELL=command.com /e:2048


14. Known Problems
-------------------

*  If you are compiling for Microsoft Windows 3.1x, and you are using the
   MetaWare -Hwin switch, you may encounter a problem with the Phar Lap
   linker. The linker will not correctly handle a variable whose size is
   between 125 and 128 bytes in length. If you have a character array of
   this size, you may see an undefined symbol error from the linker.

   When you encounter this, you have the following options:

   -  Increase the size of the array.
   -  Contact Phar Lap technical support at (617) 661-1510.
   -  Contact MetaWare technical support for an engineering update that 
      supplies a work-around for this problem.

   NOTE:  Two of our Windows example programs fail to link because of this
   problem:

      highc\win\sdk\prntfile
      highc\win\sdk\showfont

   You can resolve the problem by increasing the size of the 128-byte 
   character array in these examples to 256 bytes.

*  On some machines, you may experience problems using the debugger MDBW with
   various device drivers, memory-resident programs (TSRs), or local area
   networks.  If you cannot load a program to debug, or cannot get the
   debugger to execute, try changing your CONFIG.SYS and/or AUTOEXEC.BAT files
   to temporarily eliminate the network or device drivers.  Then reboot and
   try the debugger again.

*  There is a conflict between Phar Lap version 3.0 and 4.0 DOS extenders 
   and EMM386.  If you currently are using version 3.0 or 4.0 386|DOS-
   Extender, and you have EMM386 installed in your CONFIG.SYS file, you must 
   remove EMM386 before using the MetaWare compiler.

*  You may notice that if you run a Windows program many times without
   rebooting your machine, occasionally the program will start up, but never
   display a window.  (The Windows task switcher thinks that the program is
   running, and it is actually running.)  At the present time, we have not
   determined the cause of this anomalous behavior.  If you encounter this
   behavior, simply reboot your machine.  The program will run properly after
   the machine has been rebooted.  


15. Windows Applications and OS/2
---------------------------------

Windows applications compiled with the MetaWare compiler now run in OS/2,
as well as in OS/2 for Windows.


16. Frequently Asked Questions
------------------------------

* Can I use the ADK to write VxDs (virtual 80x86 device drivers)?
    No.  The ADK can build only standard Windows applications.

* Can I use virtual memory?
    If you use the Windows global heap (GlobalAlloc()), you can use Windows 
    virtual memory.  However, ADK programs sidestep Windows memory management 
    when you use malloc().  

* I want to write a 32-bit DLL that I can call from a 16-bit application; is
  there a Call32() (or equivalent) function?
    No.  Internally, 32-bit DLLs are handled directly through the supervisor,
    and bypass Windows entirely.  The only possible way to "call" 32-bit
    code from a 16-bit program is to write an ADK program that receives
    standard window messages from the 16-bit program and calls the 32-bit 
    DLL itself.


17. Trouble-Shooting Tip
------------------------
   Are you having trouble debugging a Windows ADK program?

   *  Check:  Your Windows SYSTEM.INI file should have this line immediately
      following the [386Enh] section heading:

         device=vmw32d.386

      If this line is missing, add it.



Document number:  RM-4704-002