       This file contains basic documentation for the DosWin32 pack.

The use and distribution of DosWin32 pack is permitted ONLY by accordance with
the DosWin32 pack license agreement (see file license.txt).

DosWin32 is distributed in two archives: basic DW32CORE.ZIP (end-user files)
and optional DOSWIN32.ZIP (files for development).
According to the license agreement the same files from DW32CORE.ZIP can be
included in any other software products.

----------------------------------------------------------------------------
   The general concept of DosWin32 pack is the same as that in Borland Power
Pack: the main task is not to support the DPMI applications (although some
DPMI functionality is present), but to support win32 console applications in
pure DOS.

   The DOSWIN32.RTM file is the "core" of the system. It also includes the
win9x and WinNT drivers (for development and debugging in the Windows
environment) and the DPMI host (for working under DOS).


        I. The main restrictions and specifics (end-user information)

-----
1. Required software and hardware configuration:

1.1. Minimal required hardware: x486 (not SX) and at least 16MB RAM.

1.2. The DOS-7 (from the Windows9x package) can be used as "basic" OS.
     For development and debugging purposes Win9x and
     WinNT (NT4SP3 and higher) Dos-Box can be used.
     MS DOS version 5 and higher versions are supported.

-----
2. To run programs created by UniLink (see UniLink description) with DosWin32
   auto-loading stub, the DOSWIN32.RTM file must be in the PATH.

-----
3. Inside the emulated win32 system the SystemDirectory and WindowsDirectory
   variables point to the directory with DOSWIN32.RTM.

-----
4. The DosWin32 program can allocate up to 1Gb physical memory, although it
   can use about 3Gb of virtual address space under DOS. Under Win9x/WinNT, the
   accessible memory size depends on the particular OS. DosWin32 can work
   under "pure" DOS and with loaded HIMEM or HIMEM+EMM386. The last case is
   slightly slower.

-----
5. If the physical memory is not sufficient (in DOS) then swapping to
   the disk can be used. To turn on swapping you need to create a swap
   file of sufficient size.
   If that file exists when DosWin32 is started, the swap subsystem is
   automatically initialized. The minimal size of swap file is 0.5Mb and the
   maximal - 2Gb (DOS restriction). Default swap file name is DOSWIN32.SWP
   (looked up in the CURRENT directory), but you can specify any file in
   environment variable DW32SWP.

   CAUTION: You MUST specify the FULL path to the swap file in the environment
              variable.

   NOTE: Swapping in DOS is very slow and should be used when there is no
         other solution. To maximize the speed, the swap file should be
         placed in the drive with a cluster size of 4Kb (8 sectors).

-----
6. CAD (Ctrl-Alt-Del) is "blocked" all the time when the DosWin32 is active.
   The phantom floppy (when only one floppy drive is present) also doesn't
   work.

-----
7. Don't forget to load all resident programs you use (mouse driver, smartdrv,
   national keyboard drivers etc.) BEFORE DosWin32 starts.

-----
8. The PE program can be launched under the emulator in three ways:
   1. If it was linked by UniLink with -ax[y] option it will load DosWin32
      automatically.
   2. You can start DosWin32 "by hand" through run32 command.
   3. When DosWin32 is resident all PE applications are started in 32-bit
      mode.

-----
9. There are two small programs in DosWin32 pack: RD32.EXE and RUN32.EXE.
   The first is a td32 debugger launcher and the second is used by two ways:
   it starts a PE application or it loads the DosWin32 core and makes
   it resident in the memory.
   When you want to start the PE program without the DosWin32 stub under
   emulator, you need to type:

       run32 <program_name> <program_parameters>

   The program is started in the PE mode and after its termination the
   DosWin32 core will be unloaded.
   More common is to use run32 to make DosWin32 resident. To do this run
   run32 without arguments. When DosWin32 is resident, neither run32
   nor PE-stub's are needed anymore. All started tasks are checked for
   the PE header and launched in the appropriate mode. Thus the win32 program
   start time is significantly shorter. But another side is that 16-bit
   task executions are very slightly slower.
   The resident DosWin32 core can be unloaded by the 'exit' command.

   NOTE: if the loaded program uses "external" (not implemented in the
         DosWin32 core) DLLs, they have to be found in the search path.

-----
10. The registry database uses the DOSWIN32.RGD file in the DOSWIN32.RTM
    directory. If it does not exist, it is created when DosWin32 is started.

    CAUTION: If the registry file is corrupted then the DosWin32 core cannot
             be loaded. This is a fatal error. The only solution is to delete
             the corrupted file. If you want to use the registry don't forget
             to make a backup copy.

-----
11. The functions that use the system ini-file (win.ini) work with
    the DOSWIN32.INI file placed in the DOSWIN32.RTM ("system") directory.

-----
12. When the DosWin32 core is loaded (is resident or when "child" programs
    are running) even the DOS applications can use the clipboard.

-----
13. If the program is terminated by an exception, the error information is
    not only printed on the screen, but can also be stored in the error log file.
    To turn on this feature you need to define the environment variable
    DW32LOG with the FULL path to the error log file.

    NOTE: If the file name is "*" then the log file DOSWIN32.LOG in DOSWIN32.RTM
          directory is used. If the file name is "." the file DOSWIN32.LOG
          is created in the current (at the emulator start time) directory.

    CAUTION: If the file name has the '+' symbol placed before its name then
             it is interpreted not as a part of the file name, but as a full
             diagnostic flag. When this flag is set, ALL the messages
             concerning the program or library loading errors will be written
             into this file. This flag affects the children processes too
             (LoadLibrary/CreateProcess/etc).

-----
14. If the unresolved imports are detected in the program loading phase,
    then the loader asks for program launch confirmation. If the answer is
    "Y[es]" and some of these unresolved imports are called, the error message
    would be generated (on the screen and to the log, if active) with the
    information about the import and where it was called from.

-----
15. DosWin32 works with long file names (LFN), but because DOS does not
    support LFN, using LFN slows down performance and buffering. However long
    names are preserved even when old 16-bits programs work.

    For the proper work with LFN the PROPER current CodePage must be set
    (the COUNTRY.SYS must be loaded for all countries other than the USA).

    NOTE:      CodePages (countries) with DBCS are not supported. For these Code
               Pages the LFN features MUST be disabled - otherwise DosWin32
               will not be loaded.

    To disable the LFN suport please set the environment variable
                 DW32LFN=-

-----
16. When working with resources the language is "calculated" from
    the DOS country code (COUNTRY.SYS). The language can be changed
    (for example, for countries with more than one language) using
    the environment variable DW32RLC=nn, where nn is the two low hex
    digits from LANGID. This is equivalent to the ResourceLocale of
    the win32 registry, but (for example) if in win32 the code for
    spanish is 0000040A, in Doswin32 0A must be used.
    If this variable is set to 00, the ResourceLocale will always be NEUTRAL.

    NOTE:      The DW32RLC variable can be 00 or 09 (english is always
               available) or MUST be equal to the same CodePage as in DOS.
               Otherwise the environment variable would be ignored.

-----
17. DosWin32 uses the TZ environment variable. If it is defined and
    has a xxx[+/-]n[n][yyy] format, the xxx is used as the timezone name and
    [+/-]n[n] as the time shift from UTC (in range -12 -:- +12 hours). If yyy
    is present then:
        a) yyy is the name of the daylight saving mode.
        b) the +1 hour value is added to the time shift.

    NOTE:      The daylight saving time is not calculated from the date. If
               yyy is defined, it is used in the current DosWin32 session.

-----
18. By default host allocates all physycal memory (up to 1Gb :), but You can 
    restrict memory size used by host (e.g. left memory for using by other  
    extenders when DosWin32 is loaded).  For do this set appropriate value 
    (8 to 1024 MB) to environment variable DW32LIM.

-----
 19. If you need to 'hide' host (for executing other extenders when DosWin32 
     is loaded) and/or 'hide' DosWin32 from jobs that check multitasking 
     environment (int 2F 1600), You can use dw32mode.com program. This program
     is placed in dw32tool.zip archive.
       The registry-editor is also placed in this archive.

---------------------------------------------------------------------------
---------------------------------------------------------------------------
        II. The general restrictions and specifications (development
            information)

1.  To run programs under debugger (currently only Borland td32) you
    use RD32.EXE from the DosWin32 pack or load DosWin32 core to the
    memory (see above) and run td32 as usual.

    NOTE: When td32 reports 'error loading program' it is useful to switch to
          the user screen (Alt-F5) to see the reason. Work this way when you
          start programs with unresolved imports.

    CAUTION: TD32 contains some VERY severe errors (in DPMI support):
               in 'System Information' menu, right click the mouse
               in the debugger window. The breakpoints are lost when the
               program is terminated, etc. The information about errors was
               sent to Borland, but they don't support td32 now. You can use
               patches and special DLLs on DosWin32 ftp as INFORMATION
               about a temporary way to bypass these errors.

-----
2.  While the context is switching (launching a child process and/or
    working with the debugger) only the "basic" context is saved
    (including FPP) for the moment. The SSE-extension context is not saved
    even if it exists. Perhaps this will be improved in the next versions.

-----
3.  The mouse control is different from that under BPP: each task has a
    "personal" hide/show mouse cursor state. The cursor state can be changed
    ONLY by ENABLED_MOUSE_INPUT (DISABLED when program is started).

-----
4.  Working with registry

4.1. The restrictions are practically the same as in Win9x, but the STRONG
     recommendation is not to save big sizes of data in the registry.

4.2. The registry is saved to the disk only when the RegFlushKey (with
     any valid key) function is called or when any task is terminated. (If
     registry contents are not changed, the registry is not saved).
     NOTE: The registry is not saved if the task terminate by stack
           overflow/invalid exception. The RegFlushKey function produce
           ERROR_CALL_NOT_COMPLETE if called from stack overflow exception
           handler.

4.3. The registry file is not locked when the system works.

-----
5.  The clipboard implementation

    only CF_TEXT and CF_OEMTEXT and RegisterClipboardFormat are supported.
    When DosWin32 core is in resident, the clipboard for DOS tasks is also
    supported.

    CAUTION: The translation between ANSI and OEM formats is not performed,
             because ANSI and OEM codepages are the same.

    NOTE: Because the MS DOS programs check the presence of Windows enhanced
          mode before they start to work with the clipboard, the system
          answers them that the Windows version 22.0 is present.

5.1 Restrictions of RegisterClipboardFormat():
     a. Maximum possible name length - 62 chars (without 0)
     b. Maximum possible registered formats at the same time - 15
     c. Clipboard has a single buffer - You cannot store multiple
        data in it in different formats simultaneously.

---------------------------------------------------------------------------
---------------------------------------------------------------------------
        III. The system peculiarities (development information)

1.  Identification. If you want to determine if your programs work under
    DosWin32, the simplest method is to use GetVersion/GetVersionEx.

1.1. GetVersionEx
     Under DosWin32 the szCSDVersion field contains the "DW32" string and the
     dwPlatformId field - number 3 (this is needed for the correct work of
     Borland RTL that changes some behaviour under Borland 32rtm).

1.2. GetVersion
     GetVersion has the possibility to find that the program works under
     DosWin32 and the basic OS type:
        if(dwVersion > 0xF0000000) { // doswin32
            // dwWindowsMinorVersion -> EMULATOR_VERSION
            dwBuild    = (DWORD)LOWBYTE(HIWORD(dwVersion));
            dwExecMode = (DWORD)HIBYTE(HIWORD(dwVersion)) & 3;
            // 0 - in DOS, 1 - on win9x, 2 - on NT
        }

-----
2.  When working with the memory mapped files, note that the different
    MapViews are NOT coherent. MapView with FILE_MAP_WRITE would always be
    written to the file regardless of the data modifications. The use of the
    file mapping with FILE_MAP_WRITE is not recomended for DosWin32 programs
    because of poor performance (in some cases).
    The main goal of the file mapping under DosWin32 is to support "old"
    programs (such as link v7.1).
    The restrictions for the lpBaseAddress parameter of the
    MapViewOfFileEx() function are the same as under Windows NT.

-----
3.  There is a nontrivial problem with the OEM-ANSI / ANSI-OEM translations.
    Console applications get the input string in the ANSI encoding but the
    output is processed in the OEM encoding (for instance, in the message
    "File not found: <input_file>"). Under DosWin32 ANSICP == OEMCP, therefore
    the translation is a simple copy. On the other hand the data can be read
    from a file and so must be really translated.

    We could not find an automatic method to solve this problem and we suggest
    using two new functions: dpmiOemToChar[Buff]/dpmiCharToOemBuff which
    replace OemToCar[Buff]/CharToOem[Buff] respectively. These functions
    perform real translations (but not for all code pages). The current
    version supports code pages 437, 866, 850, 852, and 775.

    If you link your program by UniLink you can link these functions
    statically, if not - you can obtain their addresses by GetProcAddress (in
    user32).

    There is no difference in working under Win32 and DosWin32 as these
    functions perform the real translation.

    CAUTION: You MUST call dpmiNlsInit() BEFORE using these functions.
             The prototypes of all these functions can be found in ulnkhdr.h.

-----
4.  Peculiarities of using the long names (GetShortPathName/GetLongPathName).

4.1. Usually the console applications work with !AreFileApisANSI. If you
     call SetFileApisANSI under DosWin32, it does nothing. So you have to
     translate ANSI strings yourself (dpmiCharToOem[Buff]A).

4.2. The best is to call GetShortPathName before the file operations (if
     your program can work with long names).

4.3. The GetShortPathName (and GetLongPathName) oddities

4.3.1. The proper error code is always set (Win32 sets FILE_NOT_FOUND even
       when it should be PATH_NOT_FOUND, and PATH_NOT_FOUND is set
       only with a bad disk name).

       CAUTION: If the input name is directory (i.e. it terminates with '\\')
                and if there is no such directory, the error code is set
                to PATH_NOT_FOUND. If you try to access the "illegal"
                device the error code is set to ERROR_BAD_DEVICE (see below).

4.3.2. In all cases the path/filename is checked for its existence.
       GetLongPathName (under DOS and Win9x) preserves the case in the
       file names.

4.3.3. The defaults are always expanded i.e. if the input string is something
       like ".", the output would be the full name of the current
       directory and for the string "D:" - the full name of the current
       directory on drive D:. The whole effect is equivalent to calling
       GetFullPathName followed by GetShortPathName/GetLongPatName under
       MS Windows. The combinations '.\' are removed and '..\' are processed.
       In other words, the output string contains the absolute full path
       (in 8.3 for GetShortPathName).

4.3.4. The functions DO NOT work with the "network" path and with such a path as
       "\\\\.\\A:". Moreover, the functions work ONLY with direct-access
       devices.

       CAUTION: The functions DO NOT work with CD-disks. In such cases
                you will get an ERROR_BAD_DEVICE error code.
                These functions do not work with SUBSTed drives neither.

4.3.5. A GetShortPathName extension. Using GetShortPathName solves all
       problems with long names for OPEN_EXISTING, but not for
       CREATE_NEW. The GetShortPathName extension should be used for the
       last case.

       IF the szBuff counter is less than zero, then -(long)szBuff is used
       as the counter and the function behaviour is different when it works
       with the LAST path element (it could be a file or a directory):
          a) If a file with the given name (long or short) exists, the
             rest of processing is as usual.
          b) If no files are found and the name is 8.3, then this name is
             returned (but the error code is set - so you can check that the
             file is "new").
          c) If no files are found and the name is long, then a short name is
             generated and returned. It is a guarantee that the returned name
             is unique (the error code is set too).

    NOTE: The names returned by GetLongPathName CAN NOT be used for file
          operations if LFN-support is disabled.

    CAUTION: GetShortPathName/GetLongPathName under DosWin32 in NT works
             differently than in DOS - it "understands" NTFS, for instance.

    NOTE: NT GetLongPathName works ONLY for the file name and for the path
          parts that are not directly specified. If, for example, you specify
          the path in uppercase it will not be converted into realcase.

    NOTE: in NT4 the name remains in the form equivalent to what
          GetFullPathName returns.

-----
5.  SetEnvironmentVariable under Win32 allows you to define the variables such
    as '=C:' with any value. In these cases, the file operation with an
    "uncompleted" path will generate an error. Under DosWin32 the error is
    generated in SetEnvironmentVariable if the path does not exist. In other
    words such variables are "synchronized" respectively with CurrentDirectory.

-----
6.  The phantom floppy drive is absent for all disk operations (including
    GetLogicalDrives). This is true even for DOS tasks while DosWin32 is
    active.

-----
7.  The maximal length of the value string for the ini-file access functions
    is 2Kb. Therefore the size of the struct in Get/Write-PrivateProfileStruct
    must be less than 1Kb.
    The difference to Win32 is that all these functions set the real
    GetLastError error codes.

    ini-files restrictions:
        maximum file length          - 64Kb (as in Win32)
        maximum section NAME length  - 128 bytes
        maximum key NAME length      - 128 bytes
        maximum section DATA size    - file_size - section name length
        maximum VALUE length         - 2Kb
        maximum STRING length        - 2560 bytes
           (including comment)

    CAUTION: When one tries to write too long data an error is reported
             (Win32 simply truncates the data).
             If the ini-file does not contain a valid struct, working with
             the file is impossible.

-----
8.  The address space for all tasks under DosWin32 is common. Because all
    exe's are linked on the same base by default, it is impossible to launch
    one task from another if the relocation table is stripped in the exe-file.

    To solve this problem the tasks with the relocation tables are loaded and
    relocated to the highest address in the virtual address space, leaving the
    lowest memory for tasks without relocations.

    CAUTION: If some program is expected to be executable in the
             fixed memory range but includes a relocation table it will not
             work.

    NOTE: If in the program (library) header bit IMAGE_FILE_AGGRESIVE_WS_TRIM
          (UniLink key -GF:AGGRESSIVE) is set then the program will be
          loaded to the default base address (like a program without
          relocations).

-----
9.  While lpApplicationName==NULL in CreateProcess then the real (full)
    exe-file name is put into the command line of the loaded program.

-----
10. SetActiveConsoleScreenBuffer is very restricted in functionality. It
    is made for programs which use it to save the screen on start and to
    restore it on exit. If the ScreenBuffer is different from the current, the
    screen is erased (and the video mode 3 is set).

-----
11. SetConsoleScreenBufferSize permits only BIOS supported screen sizes.
    NOTE: If the screen size is changed the screen is erased.

---------------------------------------------------------------------------
---------------------------------------------------------------------------
        IY. Working under Win32 (development information)


   If you want to run the application under Win32 you can change the signature
   from 'PE' to 'BPE'. Or you can use run32 from the DosWin32 pack.
   The drivers needed to work under WinNT and Win9x are included in
   the main DosWin32 file DOSWIN32.RTM. The drivers are loaded dynamically and
   do not need be to installed.

   NOTE: UniLink key -aX forces it to use DPMI for the linked program.

   CAUTION: Working under NT:
              1. DosWin32 does not work under NT 3.51 and under NT4 it is
                 tested only for SP6.
              2. Under NT the small R0 driver is required. So
                 before running a DPMI-task under DosWin32 for the first time
                 you have to run the ntdinst driver installer (administrator
                 permissions are required). After the driver is installed the
                 administrator permissions are not needed anymore.
      ATTENTION: Current driver work only on Pentium or higher CPU, but package
                 included "old"-driver (old_ntdi.zip) that work at 486, but... 
                 do not work on multiprocessor/multicore configurations.
              3. GetShortPathName/GetLongPathName behaviour is
                 different from DOS/Win9x (see above).

   NOTE: To uninstall NT driver you can delete the driver file or delete
         the registry record.

              4. The support of FPP errors doesn't work under NT for the
                 programs which disable virtual interrupts.
                 If a 32-bit task launches a 16-bit DOS task which
                 generates an FPP error, the DOS task cannot process this
                 error. The driver reports this error and the task will be
                 terminated when first int 21h will be called. If the DOS task
                 was launched from the DOS session, the better choice in this
                 situation would be to close the DOS session (with 'exit').

---------------------------------------------------------------------------
        V. DosWin32 core extensions (development information)

1.  Resolving of unresolved imports.
    The current development model suggests that resolving unimplemented
    imports by users is "temporary" until this function will be included
    in the DosWin32 core. In the text below the "system DLLs" are the DLLs
    that are included in the DosWin32 core.

1.1. Due to the fact that the doswin32 core contains all system DLLs,
     the GetModuleHandle() function returns a valid HINSTANCE for them
     even if the LoadLibrary() function has not been called.

1.2. Here is the full list of the system DLLs in the current version:
     kernel32.dll, user32.dll, advapi32.dll, ole32.dll, shell32.dll,
     mpr.dll, ntdll.dll, version.dll, winmm.dll, oleaut32.dll, rpcrt4.dll,
     winspool.drv, gdi32.dll
     (gdi32.dll is a fake library. its purpose is to prevent
      the loading of the real gdi32.dll)

1.3. Console applications do not use all functions from the system DLLs.
     Because of this not all exported functions are implemented in the system
     DLLs. Also some exported functions are "dummy" functions (returning
     ERROR_CALL_NOT_IMPLMENTED, ERROR_INVALID_HANDLE, etc).

1.4. If an entry point in a system DLL is not implemented in DosWin32,
     then the programmer can use the GetProcAddress() function to
     determine this fact. But this approach leads to a system-dependent code
     and will not work for existing programs. Any entry point
     required by a substantial number of programs will be added into
     the core in the future versions. A temporary workaround is
     descibed in 1.5.

1.5. To solve the "unresolved imports" problem an extension DLL
     is introduced. Its name is DOSWIN32.EXT and it resides in the
     %SystemDirectory%. This DLL may be absent but if it exists,
     it will be loaded for all programs (exceptions are described in 1.7).
     When the GetProcAddress() function for an entry point
     of any system DLL is to return NULL, the exported functions of
     DOSWIN32.EXT are scanned for the specified name
     (or number). If the exported function is found then it is used
     to replace the missing entry point.
     CAUTON:    If %SystemDirectory% contains the DOSWIN32.EXT file and it
                is NOT a valid DLL, no programs can be started.

1.6. DOSWIN32.EXT is an ordinary DLL, but all its imports can refer ONLY
     to the system DLLs. The main task for this DLL is to define dummy
     functions which are not present in the core.
     CAUTION:   If you use Borland's ilink32 to build this DLL,
                keep in mind that it has a bug and always creates an
                entry point even if you do not ask for it.

1.7. If you do NOT need to load the extension DLL with your program
     (to save memory and for quicker load time) you can mark your program
     not to load this DLL. This is accomplished by setting
     the IMAGE_FILE_BYTES_REVERSED_LO attribute (this attribute is ignored
     by Win32 on x86).
     NOTE: Some old linkers (Borland tlink32 version < 5.0, Watcom wlink)
           always set this bit. New linkers (ilink32 from BCB >= 4, link
           from VC >= 4) do not.
     UniLink sets this bit if you use -ay or -aY command line switches
     instead of -ax or -aX).

-----
2.  "Pseudo-system" DLLs.
    If a system DLL is not included in the DosWin32 core then you can create
    your own DLL with the same name (commdlg.dll, for instance, but
    this is dangerous: imagine that the user copies your DLL to the Win32
    system directory and overwrites the standard DLL.
    To solve this problem the DLL loading process has been modified.
    For all LoadLibrary() calls (including the static linked DLLs), if
    the full path to the library is not specified and the file
    extension is .DLL (or not specified), then DosWin32 will look for
    a file with an .RTM extension in the %SystemDirectory%. If such a
    file is found, then it will be loaded, otherwise the normal DLL
    search sequence will be performed. So, when LoadLibrary("mydll")
    is called and a file named "mydll.rtm" is present in the
    %SystemDirectory%, then the mydll.rtm file will be loaded.

-----
3.  For the extension DLLs (DOSWIN32.EXT and '.RTM' DLLs) which
    contain only "dummy" routines a special "forward-export" method
    was created. In other words the extension DLLs can be an export-only
    DLLs, i.e. it contains only the exports section (these DLLs can be
    created by the UniLink linker).

3.1. The forward-exports are created (as usual ones) by using a def-file.
     To create a def-file from the text description of the "dummy" routines
     please use the makedef.exe tool from the SAMPLES directory.
     The file format of this file is described in the makedef.txt file.

----------------------------------------------------------------------------

4.  Working with the third-party plug-ins.
    If you want that the LoadLibrary() call to be successful
    in the presence of unresolved imports, you can set bit 0x40
    in the FileHeader.Characteristics field of the executable file.
    This bit is not used in any Win32 system. You can set this
    bit by using a hex editor (offset 0x16 from the 'PE' signature).

4.1. In additon, if this flag is set and if the library name includes the full
     path, all calls to LoadLibrary[Ex] will get the short file name using
     GetShortPathName() before performing the search.

----------------------------------------------------------------------------

5.  Send your requests to include functions and "dummy" routines in
    the DosWin32 core to support@doswin32.com (please describe the program
    for which they are needed).
