Delphi does WDosX
================= 
guidance for the adjustment of the Delphi 5.01 VCL core units for WDosX 32bit
DOS Extender

Version history
---------------
	10 May 2000: Original document created

Outline
-------
	I. Requirements
	II. Preparation
	III. Creation the unit WDosSysUtils
	IV. Creation the unit WDosClasses
	V. Creation the unit WDosContnrs
	VI. Notes
	VII. Disclaimer
	VIII. Contact with the author

I. requirements
---------------
	1. Delphi 5 Professional or Enterprise (SOURCE code of the VCL is
           necessary)
	2. Update version for Delphi 5.01 (Professional or Enterprise)
	3. Turbo Assembler 5 (TASM32.EXE is necessary; available on the Borland
           C++Builder 4 Professional+ CD)
        4. the file LibWDos50.zip (available on the DWP)
        5. Common sense

II. Preparation
---------------
For the creation of the WDosX VCL core unit it is advisable to copy the
following files into the work directory $(delphi)\libwdos:
	* WDosWinApi.pas,
	* WDosMessages.pas,
	* WDosCheck.pas,
	* WDosForms.pas (these files are contained in the Zip file
          LibWDos50.zip).

Further the following files from the directory must be copied $(delphi)\source
into the work directory:
	* Ffmt.asm,
	* Se.asm,
	* Classes.pas,
	* Consts.pas,
	* Contnrs.pas,
	* SysConst.pas,
	* SysUtils.pas and
	* TypInfo.pas.

For the successful assembly of Ffmt.obj the turbo-assembler (TASM32.exe) must
be available in the search path.

III. Creation the unit WDosSysUtils
-----------------------------------
A prerequisite for the compiling the unit WDosSysUtils forms a being present
of the file Ffmt.obj, which is unfortunately not constituent of the source
code library of Delphi. It can be generated however with the help of the
turbo-assembler (TASM32.exe) from the files Ffmt.asm and Se.asm. In addition
the following instruction is to be input in the work directory:

	C:\Programme\Borland\Delphi5\LibWDos>TASM32 FFMT.ASM

As result one receives the looked up file Ffmt.obj. Now the more difficult
part of the work follows. Start Delphi and open you the unit SysConst.pas in
mentioned above the work directory. Store it afterwards under the name
WDosSysConst.pas again. Insert afterwards the following copyright note:

  --8<-------------------BEGIN-----------------------------

  {*******************************************************}
  {                                                       }
  {       Borland Delphi Runtime Library                  }
  {                                                       }
  {       Copyright (C) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}


  unit WDosSysConst;

  --8<-------------------END-------------------------------


The resourcestring clause must be located now in the line 19. Proceed
afterwards into the line 51 and to take the here following modification:


  --8<-------------------BEGIN-----------------------------
  (*SException = 'Exception %s in Modul %s bei %p.'#$0A'%s%s';*)
    (**)
    SException = 'Exception %s in Modul %s bei %p.'#$0A#$0D'%s%s';
    (**)
  --8<-------------------END-------------------------------


Thus all necessary modifications at the file WDosSysConst.pas are executed.
You can store it now.

The principle of the modifications should be clear thereby: program sections,
which are not suitable for WDosX, are out-commentated with the comment
symbols (* and *). Additionally inserted source text is indicated by
empty comments (**) before and behind the inserted text.

Now we can near-make ourselves to the creation the actual unit of this section.
Open in addition the unit SysUtils.pas in mentioned above work directory.
Store it now under the name WDosSysUtils.pas. Insert the afterwards following
copyright note:

  --8<-------------------BEGIN-----------------------------

  {*******************************************************}
  {                                                       }
  {       Borland Delphi Runtime Library                  }
  {       System Utilities Unit                           }
  {                                                       }
  {       Copyright (C) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}



  unit WDosSysUtils;
  --8<-------------------END-------------------------------


The uses clause must be located now in the line 23. Amend these as follows:

  --8<-------------------BEGIN-----------------------------
  uses (*Windows, SysConst*) (**)WDosWinApi, WDosSysConst(**);
  --8<-------------------END-------------------------------


Be received afterwards to the line 186 and to add you a beginning of comment:

  --8<-------------------BEGIN-----------------------------
  (*
  { This is used by TLanguages }
  In der Zeile 217 endet der Kommentar:
      property Ext[Index: Integer]: string read GetExt;
    end;
  *)
  --8<-------------------END-------------------------------


It continues to go in the line 491. Commentate the function LANGUAGES out:

  --8<-------------------BEGIN-----------------------------
  (*
  function Languages: TLanguages;
  *)
  --8<-------------------END-------------------------------


In the line 928 the function ExpandUNCFileName must be out-commentated:

  --8<-------------------BEGIN-----------------------------
  (*
  function ExpandUNCFileName(const FileName: string): string;
  *)
  --8<-------------------END-------------------------------


In the line 942 the function ExtractShortPathName is out-commentated:

  --8<-------------------BEGIN-----------------------------
  (*
  function ExtractShortPathName(const FileName: string): string;
  *)
  --8<-------------------END-------------------------------


Go to line 2161 and insert a beginning of comment:

  --8<-------------------BEGIN-----------------------------
  (*
  { Thread synchronization }
  --8<-------------------END-------------------------------


In Line 2197 the comment ends:

  --8<-------------------BEGIN-----------------------------
      procedure EndWrite;
    end;
  *)
  --8<-------------------END-------------------------------


It continues to go in the implementation section in the line 2518. Replace
the functions AnsiStrLower and AnsiStrUpper as follows:


  --8<-------------------BEGIN-----------------------------
  function AnsiStrLower(Str: PChar): PChar;
  begin
  (*
    CharLower(Str);
    Result := Str;
  *)
  (**)
    Result :=StrLower(Str);
  (**)
  end;

  function AnsiStrUpper(Str: PChar): PChar;
  begin
  (*
    CharUpper(Str);
    Result := Str;
  *)
  (**)
    Result :=StrUpper(Str);
  (**)
  end;
  --8<-------------------END-------------------------------


It continues to go in the line 2895, it must read as follows:

  --8<-------------------BEGIN-----------------------------
  (*Windows*) WDosWinApi.FindClose(Handle);
  --8<-------------------END-------------------------------


Same applies to the lines 2993 and 3000. Here the reference to the Windows unit
must be likewise modified:

  --8<-------------------BEGIN-----------------------------
  (*Windows*) WDosWinApi.FindClose(F.FindHandle);
  ...
  Result := (*Windows*) WDosWinApi.DeleteFile(PChar(FileName));
  --8<-------------------END-------------------------------


Go next to line 3124 and comment-out the functions
GetUniversalName and ExpandUNCFileName (until line 3194):

  --8<-------------------BEGIN-----------------------------
  (*
  function GetUniversalName(const FileName: string): string;
  ...
      Result := GetUniversalName(Result);
  end;
  *)
  --8<-------------------END-------------------------------


Go afterwards to the line 3124 and comment-out the functions GetUniversalName
and ExpandUNCFileName (to line 3194):

  --8<-------------------BEGIN-----------------------------
  (*
  function ExtractShortPathName(const FileName: string): string;
  ...
      GetShortPathName(PChar(FileName), Buffer, SizeOf(Buffer)));
  end;
  *)
  --8<-------------------END-------------------------------


In the line 6073 the DebugHook must be set to 1, so that Delphi treats the run
time exception also and calls no external debugger:

  --8<-------------------BEGIN-----------------------------
    AbstractErrorProc := @AbstractErrorHandler;
    (**)
    DebugHook := 1; { forces Delphi5 exe to handle exceptions him self }
    (**)
  end;
  --8<-------------------END-------------------------------


For alternation something music, the procedure Beep must be modified:

  --8<-------------------BEGIN-----------------------------
  procedure Beep;
  begin
  (*
    MessageBeep(0);
  *)
    Write(#07);
  end;
  --8<-------------------END-------------------------------


Now it continues in the line 6378; the procedure InitSysLocale must be
modified something. First the var paragraph:

  --8<-------------------BEGIN-----------------------------
  procedure InitSysLocale;
  var
    DefaultLCID: LCID;
    DefaultLangID: LANGID;
  (*
    AnsiCPInfo: TCPInfo;
    I: Integer;
    J: Byte;
  *)
  --8<-------------------END-------------------------------


Subsequently, still something to comment-out in the implementation starting
from line 6401:

  --8<-------------------BEGIN-----------------------------
    SysLocale.FarEast := GetSystemMetrics(SM_DBCSENABLED) <> 0;
  (*
    if not SysLocale.FarEast then Exit;

    GetCPInfo(CP_ACP, AnsiCPInfo);
    with AnsiCPInfo do
    begin
      I := 0;
      while (I < MAX_LEADBYTES) and ((LeadByte[I] or LeadByte[I+1]) <> 0) do
      begin
        for J := LeadByte[I] to LeadByte[I+1] do
          Include(LeadBytes, Char(J));
        Inc(I,2);
      end;
    end;
  *)
  end;
  --8<-------------------END-------------------------------


In the line 6664 times again a Windows reference is to be removed:

  --8<-------------------BEGIN-----------------------------
  SetString(Result, ModName, (*Windows*) WDosWinApi.GetModuleFileName(Module,
      ModName, SizeOf(ModName)));
  --8<-------------------END-------------------------------


In Line 7077 the same problem:

  --8<-------------------BEGIN-----------------------------
  Kernel := GetModuleHandle((*Windows*) WDosWinApi.Kernel32);
  --8<-------------------END-------------------------------


Equal afterwards in line 7084 the implementation of the not usable
TMultiReadExclusiveWriteSynchronizer begins. Thus comment out:


  --8<-------------------BEGIN-----------------------------
  (*
  { TMultiReadExclusiveWriteSynchronizer }
  --8<-------------------END-------------------------------


until line 7241:

  --8<-------------------BEGIN-----------------------------
      if (InterlockedDecrement(FCount) = 0) or WriterIsOnlyReader then
        SetEvent(FReadExit);     // release next writer
    end;
  end;
  *)
  --8<-------------------END-------------------------------


It's going on in line 7267 with class TLanguages:

  --8<-------------------BEGIN-----------------------------
  (*
  { TLanguages }
  Diese endet in Zeile 7395:
    Result := FLanguages;
  end;
  *)
  --8<-------------------END-------------------------------


Now quickly some changes to SafeLoadLibrary from line 7399 on:

  --8<-------------------BEGIN-----------------------------
  function SafeLoadLibrary(const Filename: string; ErrorMode: UINT): HMODULE;
  var
  (*
    OldMode: UINT;
  *)
    FPUControlWord: Word;
  begin
  (*
    OldMode := SetErrorMode(ErrorMode);
  *)
    try
      asm
      end;
      try
        Result := LoadLibrary(PChar(Filename));
      finally
      end;
    finally
  (*
      SetErrorMode(OldMode);
  *)
    end;
  end;
  --8<-------------------END-------------------------------


And as crowning final starting from line 7433 the finalization paragraph
easily modify:

  --8<-------------------BEGIN-----------------------------
  finalization
  (*
    FreeAndNil(FLanguages);
  *)
    FreeTerminateProcs;
    DoneExceptions;
  --8<-------------------END-------------------------------


Congratulations. Thus you are proud owner of the source code of WDosSysUtils.
To the test you should write now a small console application, which uses the
unit WDosSysUtils. This is translated error free now (hopefully). Thus we can
look now the unit WDosClasses for the second part of the evening.

IV. Creation the unit WDosClasses
---------------------------------
Open the unit Consts.pas in mentioned above working directory. Store it
afterwards with name WDosConsts.pas again. Insert afterwards the following
copyright note:

  --8<-------------------BEGIN-----------------------------

  {*******************************************************}
  {                                                       }
  {       Borland Delphi Visual Component Library         }
  {                                                       }
  {       Copyright (c) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}


  unit WDosConsts;
  --8<-------------------END-------------------------------


Thus all necessary modifications at WDosSysConst.pas are executed. You can
store it therefore.

It's going on with unit TypInfo.pas. Open it with Delphi and store it
afterwards again with the name WDosTypInfo.pas. Insert the following
copyright note:


  --8<-------------------BEGIN-----------------------------

  {*******************************************************}
  {                                                       }
  {       Borland Delphi Visual Component Library         }
  {                                                       }
  {       Copyright (c) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}


  unit WDosTypInfo;
  --8<-------------------END-------------------------------


The uses clause must be located now in the line 21. Change it as follows:

  --8<-------------------BEGIN-----------------------------
  uses (*SysUtils*) (**)WDosSysUtils(**);
  --8<-------------------END-------------------------------


Go afterwards to the line 268 and modify the uses clause in implementation
part as follows:

  --8<-------------------BEGIN-----------------------------
  uses
    (*Consts*) WDosConsts;
  --8<-------------------END-------------------------------


Thus all necessary modifications are also here executed. Store the unit
and open afterwards the main unit of this paragraph, Classes.pas.
Store it afterwards with the name WDosClasses.pas again. Input now
the following copyright note:


  --8<-------------------BEGIN-----------------------------

  {*******************************************************}
  {                                                       }
  {       Borland Delphi Visual Component Library         }
  {                                                       }
  {       Copyright (c) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}


  unit WDosClasses;
  --8<-------------------END-------------------------------


Thus now the first uses clause is in the line 25. Modify it as follows:

  --8<-------------------BEGIN-----------------------------
  uses (*SysUtils, Windows, ActiveX*) (**)WDosSysUtils, WDosWinApi(**);
  --8<-------------------END-------------------------------


So you can see, with WDosX no ActiveX-support is available.
It's going on in line 621. Unfortunately class TStreamAdapter is not usable:

  --8<-------------------BEGIN-----------------------------
  (*
  { TStreamAdapter }
  { Implements OLE IStream on VCL TStream }
  --8<-------------------END-------------------------------


The comment-block starts at line 655:

  --8<-------------------BEGIN-----------------------------
      property StreamOwnership: TStreamOwnership read FOwnership write FOwnership;
    end;
  *)
  --8<-------------------END-------------------------------


It's going on in line 912 with class TThread. Unfortunately it must be
comment-out:

  --8<-------------------BEGIN-----------------------------
  (*
  { TThread }

    EThread = class(Exception);
  --8<-------------------END-------------------------------


The declaration-part of TThread ends in line 957:

  --8<-------------------BEGIN-----------------------------
      property OnTerminate: TNotifyEvent read FOnTerminate write FOnTerminate;
    end;
  *)
  --8<-------------------END-------------------------------


Further more the global variable global name space disturbs in line 1177:

  --8<-------------------BEGIN-----------------------------
  (*
  var
    GlobalNameSpace: TMultiReadExclusiveWriteSynchronizer;
  *)
  --8<-------------------END-------------------------------


In line 1210 an additional function declaration ReadInheritedComponentResFiles
is necessary. It's unseful together with unit WDosForms for reading ressource
files of forms (*.dfm) and to create respective initialize all TForm objects.

  --8<-------------------BEGIN-----------------------------
  procedure WriteComponentResFile(const FileName: string; Instance: TComponent);
  (**)
  procedure ReadInheritedComponentResFiles(Instance: TComponent;
      RootAncestor: TClass);
  (**)
  --8<-------------------END-------------------------------


The uses clause in implementation part (line 1265) must be modified as follows:

  --8<-------------------BEGIN-----------------------------
  uses (*Consts, TypInfo*) (**)WDosConsts, WDosTypInfo(**);
  --8<-------------------END-------------------------------


All references to GlobalNameSpace must be out-commentated. The appropriate
lines are with 1646 and 1659. The following source text sample demonstrates 
the methodology:


  --8<-------------------BEGIN-----------------------------
  (*
    GlobalNameSpace.BeginWrite;
  *)
  ...
    finally
  (*
      GlobalNameSpace.EndWrite;
  *)
    end;
  --8<-------------------END-------------------------------


In line 1717 after function WriteComponentResFile belongs following
implementation of the additional function ReadInheritedComponentResFiles:

  --8<-------------------BEGIN-----------------------------
  (**)
  procedure ReadInheritedComponentResFiles(Instance: TComponent;
      RootAncestor: TClass);

    function InitComponent(ClassType: TClass): Boolean;
    var
      pTd: PTypeData;
      FileName: string;
    begin
      Result := False;
      if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
      Result := InitComponent(ClassType.ClassParent);

      pTd := GetTypeData(ClassType.ClassInfo);
      FileName := pTd^.UnitName + '.dfm';
      try
        Instance := ReadComponentResFile(FileName, Instance);
      except
        raise EResNotFound.CreateFmt(SResNotFound, [FileName]);
      end;
    end;

  var
    LocalizeLoading: Boolean;
  begin
    LocalizeLoading := (Instance.ComponentState * [csInline, csLoading]) = [];
    if LocalizeLoading then BeginGlobalLoading;  // push new loadlist onto stack
    try
      InitComponent(Instance.ClassType);
      if LocalizeLoading then NotifyGlobalLoading;  // call Loaded
    finally
      if LocalizeLoading then EndGlobalLoading;  // pop loadlist off stack
    end;
  end;
  (**)
  --8<-------------------END-------------------------------


In lines 4146, 4196, 5091 and 5139 again the references to GlobalNameSpace 
must be comment-out.


Starting from line 7307 the implementation of TTread needs to be
out-commentated:

  --8<-------------------BEGIN-----------------------------
  (*
  { Thread management routines }
  ...
      ExceptionRecord: PExceptionRecord;
    end;
  *)

  var
    ThreadLock: TRTLCriticalSection;
  (*
    ThreadWindow: HWND;
  ...
  --8<-------------------END-------------------------------


Here it is to be noted that the variable ThreadLock may not be out-commentated.
TThread ends in the line 7547:

  --8<-------------------BEGIN-----------------------------
    GetExitCodeThread(H, Result);
  end;
  *)
  --8<-------------------END-------------------------------


The implementation of class TStreamAdapter start at line 8201:

  --8<-------------------BEGIN-----------------------------
  (*
  { TStreamAdapter }
  --8<-------------------END-------------------------------


and ends in line 8386 with:

  --8<-------------------BEGIN-----------------------------
    Result := E_NOTIMPL;
  end;
  *)
  --8<-------------------END-------------------------------


The last but one caper takes place in the initialization paragraph in
line 8410 with:

  --8<-------------------BEGIN-----------------------------
    AddModuleUnloadProc(ModuleUnload);
  (*
    GlobalNameSpace := TMultiReadExclusiveWriteSynchronizer.Create;
  *)
    ClassList := TThreadList.Create;
  --8<-------------------END-------------------------------


And forms the crowning termination with the finalization paragraph in line 8416
and 8430:

  --8<-------------------BEGIN-----------------------------
  finalization
    UnRegisterModuleClasses(HInstance);
  (*
    GlobalNameSpace.BeginWrite;
  *)
    FreeIntConstList;
  ...
    GlobalLists.Free;
  (*
    FreeThreadWindow;
    GlobalNameSpace.Free;
    GlobalNameSpace := nil;
  *)
    RemoveModuleUnloadProc(ModuleUnload);
  --8<-------------------END-------------------------------


Again congratulations, if you created it until here. Thus you are now also
owner of the source code of WDosClasses.pas. To test it you should write a
small console application again, which uses the unit WDosClasses. This is
translated error free now (hopefully).

V. Creation the unit WDosContnrs
--------------------------------
It's advisable to adapt also the unit Contnrs.pas for WDosX. This unit is
quite useful for handling object und component lists and for the component
TwdxApplicationEvents is needed beyond that. The adjustment is quite simple
compared with WDosSysUtils and WDosClasses. Open the file Contnrs.pas in
Delphi and store it afterwards with name WDosCntnrs.pas again.
Insert the following copyright note:

  --8<-------------------BEGIN-----------------------------
  {*******************************************************}
  {                                                       }
  {       Borland Delphi Visual Component Library         }
  {                                                       }
  {       Copyright (c) 1995,99 Inprise Corporation       }
  {                                                       }
  {       modified for Delphi 4, 5 WDosX DOS-Extender     }
  {       Copyright (c) 2000 by Immo Wache                }
  {       e-mail: immo.wache@t-online.de                  }
  {                                                       }
  {*******************************************************}

  unit WDosContnrs;
  --8<-------------------END-------------------------------


The uses clause must be located now in the lines 17 and 18. Amend these as
follows:

  --8<-------------------BEGIN-----------------------------
  uses
    (*SysUtils, Classes*) (**)WDosSysUtils, WDosClasses(**);
  --8<-------------------END-------------------------------


So, this was already everything. Thus the creation of the WDosX VCL core
unit is final. Further notes to the use of WDoxX with Delhi are in the
following paragraph.

VI. Notes
---------
Closer information for the use of WDosX as well as Delphi finds you on my
homepage at
	http://home.t online.de/home/immo.wache/dwp/

WDosX from Michael Tippach is available at following address:
	http://www.wuschel.demon.co.uk/

VII. Disclaimer
---------------
As usual the use of WDosX with Delphi takes place on own risk. The author does
not take over any adhesion for damage by application of this software. Further
it is to be considered that Delphi is originally not intended for use with DOS,
like represented here.


VIII. Contact the author
------------------------

	Immo Wache
	Willem-Barents-Str. 5
	D-10106 Rostock
	Germany

	e-mail:	immo.wache@t-online.de
	www:	http://home.t-online.de/home/immo.wache/dwp/en/

