/* $Id: Porting.txt,v 1.2 2000/08/11 10:54:06 sandervl Exp $ */

            Porting Win32 applications to OS/2 using Odin - 991212
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.0 Introduction
----------------

Although Odin's primary goal is to run win32 applications in OS/2 without
requiring a recompile, it is possible to port Win95/98/NT apps to OS/2
with minimal effort.
This is the first draft of this porting guide. If anything is unclear or
not mentioned, please contact the author (sandervl@xs4all.nl)

1.1 Odin32
-----------

Odin32 is the win32 compatible API provided with the Odin alpha (or daily builds).
It's consists of hundreds of win32 APIs in several dlls (kernel32, user32, gdi32 etc).
Keep in mind that Odin is still alpha software, so don't expect all apis to
work exactly like those in Windows NT.
If you find bugs, please contact the developers or send an email to the 
Odin programmers mailinglist (win32os2-wai@egroups.com).

1.2 Required tools for porting win32 apps to OS/2
-------------------------------------------------
- IBM VisualAge C++ 3.08
- OS/2 Warp 4 Toolkit (project apparently doesn't compile with 
  VAC's OS/2 headers)
  Might also work with EMX headers. (haven't tried this)
- ALP 4.0 (IBM Assembly Language Processor)
  Download the tools zipfile from http://service.boulder.ibm.com/ddk/
  (you need to register, but it's free)

It should also be possible to use Watcom or EMX to do the job, but you might
need to make some changes to our headers to make this work.

2.0 Porting Win32 applications to OS/2
--------------------------------------
In order to port win32 apps a few things have to be done:
- Change all the makefiles for VAC (or any other OS/2 compiler)
- Use Wine RC (wrc.exe) to compile the resources
- Add the Odin executable and/or dll wrapper files to the project
- Change the source code in case of compile problems

2.1 Changing the makefile(s)
----------------------------
This will probably be the most time consuming (and boring) part of the port.
You have to make sure all compiler options are correct for the project and
make some changes for compiling the resource script. (see 2.2)

To build the ported application, you must link with the necessary Odin libraries
in your makefile. These libraries (i.e. kernel32.lib, user32.lib etc) are
built when compiling Odin itself.

Paragraph 2.6 contains a skeleton makefile.

2.2 Wine's resource compiler (wrc)
----------------------------------
Wrc must be used to compile the resources of the win32 project.
Unfortunately wrc isn't completely compatible with Microsoft's rc.exe.
You might need to make some changes to the resource script in order to
make wrc happy.

Wrc produces an assembly file with the a resource tree and binary resources.
This resembles the resource section in win32 (PE) executables/dlls.
This assembly file should be added to the list of objects files in the makefile.

2.3 Odin's entrypoint wrappers
------------------------------
Kernel32 keeps track of all loaded executables and dlls. The PE loader makes
sure image objects are created when loading a win32 executable.
A ported win32 app must do this manually by calling certain kernel32 exports.

In the src\Odin32API directory of the Odin CVS tree, you'll find two wrappers:
- odinexe.cpp: Executable entrypoint (main)
- odindll.cpp: Dll entrypoint (_DLL_InitTerm)

The executable wrapper calls RegisterLXExe (exported api in kernel32) to create
an executable object and tell kernel32 where to find it's win32 entrypoint
(usually WinMain) and resources.
The dll version does the same thing. It calls RegisterLXDll to create the dll
object during a dll load and UnregisterLXDll when the dll is unloaded.
It's parameters are the dll module handle, the win32 dll entrypoint (LibMain)
and, again, a pointer to the resource object. (as produced by wrc)
The resource pointer can be NULL.
The handle returned by RegisterLxDll must be used when calling UnregisterLxDll.

In the skeleton dll entrypoint we also call ctordtorInit/Term to create/destroy
and static C++ objects.
If you don't link with odincrt.lib for the runtime C/C++ functions, you must
also call CRT_init/CRT_term (before _ctordtorInit, after ctordtorTerm).

After RegisterLXExe/Dll has finished it's job in kernel32, it will
call the exe/dll entrypoint.

2.4 Win32 source code changes
-----------------------------
Usually you shouldn't have to make many changes to the existing win32
source code. 
However, there might be a few differences between the MS SDK and Odin
headers. If you find such problems, please correct them and notify
the Odin developers.

Complex applications might be hard to port to OS/2 for several reasons:
- Compiler differences (i.e. VAC 3.08 doesn't support unnamed unions)
  VAC 3.6.5 should be a better choice for compiling win32 sources, but 
  it has it's own share of problems (bugs).
- TLS (thread local storage) data; VAC has no facilities to support this,
  so this could require a major rewrite.
  Other compilers (Watcom) may have better support for this.
  You can recognize this type of data by the __declspec(thread) keyword.
  Using the TLS apis (i.e. TlsAlloc) is no problem.
- OLE/COM objects. Wine headers aren't exactly built with C++ in mind, 
  so you'll most likely run into a lot of problems if the app uses
  these win32 features.

2.5 Exception handling
----------------------

RegisterLXExe/RegisterLXDll in kernel32 registers an exception handler
for Odin. This handler is used to support file mappings.
You must make sure that your code doesn't remove this handler from
the chain of exception handlers. 
To create a thread, use CreateThread; not _beginthread or DosCreateThread.
CreateThread takes care of setting up an exception handler, creates TLS
structures and calls dll entrypoints. 

2.6 Sample makefile
-------------------
This makefile is used to compile the MS SDK generic sample in OS/2:

PDWIN32_INCLUDE = k:\source\odin32\include
PDWIN32_LIB = k:\source\odin32\lib
PDWIN32_BIN = k:\source\odin32\bin

!include $(PDWIN32_INCLUDE)/pdwin32.mk

PROJ = GENERIC

all: $(PROJ).exe

RC = wrc
RCFLAGS = -s -I. -I$(CPPMAIN)\include -I$(PDWIN32_INCLUDE) -I$(PDWIN32_INCLUDE)\win

# Define project specific macros
PROJ_OBJS  = generic.obj 
BASE_OBJS  = resource.obj odinexe.obj 
EXTRA_LIBS = $(PDWIN32_LIB)\version.lib
GLOBAL_DEP = generic.h resource.h
RC_DEP     = resource.h


CFLAGS           = -Q  -Si -Ti -Tm+ -Ge- -Ss+ -W3 -Gm+ /Gn+ -I$(PDWIN32_INCLUDE)\Win -D__WIN32OS2__ -DDEBUG -D__i386__
CXXFLAGS         = -Q  -Si -Ti -Tm+ -Ge- -Ss+ -W3 -Gm+ /Gn+ -I$(PDWIN32_INCLUDE)\Win -D__WIN32OS2__ -DDEBUG -D__i386__

CFLAGS = $(CFLAGS) /Ge+ -I$(PDWIN32_INCLUDE)
CXXFLAGS = $(CXXFLAGS) /Ge+ -I$(PDWIN32_INCLUDE)
LDFLAGSEXE = $(LDFLAGS) /Ge+ /B"/pmtype:pm /stack:0x30000 /NOBASE /Map" \
             $(EXTRA_LIBS) $(PDWIN32_LIB)\kernel32.lib $(PDWIN32_LIB)\user32.lib \
             $(PDWIN32_LIB)\gdi32.lib os2386.lib $(PDWIN32_LIB)\odincrt.lib $(RTLLIB_O)

resource.obj: resource.asm

# Build rule for resource file
resource.asm: $(PROJ).rc $(RC_DEP)
    $(RC) $(RCFLAGS) -o resource.asm $(PROJ).rc 

# Build rule for EXE
$(PROJ).EXE: $(BASE_OBJS) $(PROJ_OBJS) resource.asm
        $(LD) $(LDFLAGSEXE) -Fe$@ $(PROJ_OBJS) $(BASE_OBJS)

# Build rule for help file
#$(PROJ).hlp: $(PROJ).rtf $(PROJ).hpj
#    $(hc) generic.hpj


# Rules for cleaning out those old files
clean:
    del *.bak *.pdb *.obj *.res *.exp *.map *.sbr *.bsc


3.0 Project participation
-------------------------

As ODIN became an open source project, everybody is kindly invited to 
contribute his/her share to the progress of the project. May it be
active coding, fixing bugs or just providing detailed information about 
examined problems.

We suggest you subscribe to win32os2-wai and the corresponsing mailing lists
on http://www.egroups.com.
In case you are interested in participating, every member of the project will 
be happy to give you direction to the right places and to give a personal 
introduction to further development of the particular modules.

