Copyright: Copyright 1995 Rainer Schnitker
Citation: Copyright 1995 Rainer Schnitker


RSXNT Help Index
RSXNT Version 1.0

Building Win32 applications with GNU-C/C++ and RSXNT

This file contains information about:

Getting started:

Introduction

Software requirements

Install RSXNT

The main RSXNT tool:

NTBIND: convert a.out file to Win32-executable

Compiling Win32 Apps:

Compiling Win32 Applications with GNU-C

Creating import libraries

Porting to GNU C:

Porting Win32 sourcefiles to GNU-C

About RSXNT:

Copyright and runtime licence

Author

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Introduction

Welcome to the first release of RSXNT, an environment for creating Win32 applications for Win95,  Windows NT and Windows 3.1 + Win32s. This product needs the EMX port of the GNU C compiler to compile your programs. The program "NTBind" in this package converts the output from the compiler into the Win32 format.

This release does not contain include header files nor any resource tools. But you can build dual-mode console programs with the standard emx include headers.

The following standard Win32 programs are supported in this release:

- native GUI programs

- native DLL programs

- Console programs

The following Win32 programs are also supported in this release

- Creating dual-mode console programs

Win32 console programs can't run under DOS, Windows 3.x or OS/2.

Dual-mode programs can run as native console application under WindowsNT / Windows95 and run under DOS with the DOS-extender RSX or EMX. Dual-mode programs can't use Win32 functions. You should only use the C-Library.

The following features are not supported in this release:

- building Chicago-style programs (buy Win95 SDK)

Missing in this release:

- old emx syscall-functions are not implemented in RSXNT.DLL

- multithread RSXNT.DLL version


Sofware requirements
Software requirements:

Minimal software requirements:

1 ) The EMX port of the GNU-C compiler

RSXNT supports EMX 0.9

(Why not DJGPP)

2 ) DOS, Windows or OS/2 to run the EMX Compiler

The GNU-C compiler is a full 32-bit unix-style program. To run this compiler under DOS, you need help from a special program called DOS-extender. The emx DOS-extender is part of the emx compiler archive (emxrt.zip). But this DOS-extender is not DPMI-compatible, you can't run this program in a DOS-box under Windows. The program rsx is a DPMI-compatible DOS-extender and can run the compiler in a DOS box under OS/2, Windows 3.1 or Windows 95. There is also a window-based extender rsxwin, that can run the compiler in a real window of Windows 3.1/95. It is possible to run this window from a GUI editor or from a IDE-shell. The rsx and rsxwin extenders are included in this archive. The documents RSX.TXT and RSXWIN.WRI contain more information.

The compiler runs in the following environments:

DOS (with emx or rsx extender)

DOS Box of Win3.x and OS/2 (with rsx extender)

OS/2 console (native with a dll emx.dll)

Windows 3.1 window (with rsxwin)

Windows 9.5 window (with rsxwin)

If you relink the compiler with the rsxnt libraries:

Win32 console

For building console Win32 programs:

1) Test platform:

a) Windows 95

b) Windows NT

Note: Win32s can't run console applications

For building GUI Win32 programs:

1) Test platform:

a) Windows 95

b) Windows NT

c) Windows 3.1 with Win32s extensions (you should use 1.25)

Note: The Windows 3.1 extention Win32s has no process synchronization and threads. Some C-Library functions like wait(), alarm(), pause() and sleep() will fail.

2) NT-SDK Win32 Headers

or other include header files from a commercial 32-bit compiler (Watcom C++ has been tested). The Linux Wine Project contains only 16-bit headers. Someone should write 32-bit headers.

3) Resource compiler

If you want to include a menu, dialog or bitmap.

Is there a public domain resource compiler ?


Install RSXNT

Emx compiler:

Get the following files from EMX 0.9a compiler package:

Base1:

emxrt.zip	emx runtime package

emxdev.zip	files required for developing programs with emx

gnudev.zip	the GNU C compiler, the GNU debugger, and other tools

Base2:

gppdev.zip	additional files for GCC required for compiling C++ programs

gobjcdev.zip	additional files for GCC required for Objective C

On problems with the C++ compiler there are updated files:

EMXFIX06.ZIP	runtime fixes

GCC270B1.ZIP	GCC 2.7.0 update

GCC270B2.ZIP	GPP, GOBJ 2.7.0 update

RSXNT:

1) Copy Runtime DLL (RSXNT.DLL) to your Windows system directory:

file: c:\rsxnt\bin\rsxnt.dll

to:   c:\windows\system

2) Copy header file (WINGNUC.H) to your EMX include directory:

file: c:\rsxnt\include\wingnuc.h

to:   c:\emx\include

You can also include "\rsxnt\include" in you compiler include path.

3) Setting up you path environment:

To run the rsxnt tools without writing the full path.

Example:

PATH=C:\DOS;C:\WINDOWS;C:\TOOLS;C:\RSXNT\BIN

Write this statements in your CONFIG.SYS or AUTOEXEC.BAT.

4) Setting up compiler library path:

Update the GNU-C library environment to the rsxnt lib directory

Example:

SET LIBRARY_PATH=D:/EMX/LIB;C:/RSXNT/LIB

Write this statements in your AUTOEXEC.BAT or in your own EMX environment file.

5) For using SDK files: Setup compiler include path:

Update the GNU-C include environment to your NT-SDK include directory. The SDK directory must follow the directory where you copy the "wingnuc.h" files.

Example:

SET C_INCLUDE_PATH=D:/EMX/INCLUDE;E:/NTSDK/INCLUDE

If you want to compile C++ programs:

Example:

SET CPLUS_INCLUDE_PATH=D:/EMX/INCLUDE.CPP;E:/NTSDK/INCLUDE

Write this statements in your AUTOEXEC.BAT or in your own EMX environment file.


NTBIND

NTBIND converts your GNU-C a.out file to the Win32 EXE format.

It does:

* Build Win32 "PE" header

* Copy text and data sections to the Win32 file

* Collect import calls and write import section

* Collect export calls and write export section

* Converts GNU-C relocation to Win32 relocation's

* Modify code to use _stdcall statement

Syntax:

NTBIND aout-name [options]

Options:

-o name

the name of the exe/dll file

-d name

the name of the dll definition file (export entries)

-s name

the name of the stub file (dosstub.dos or dosstub.rsx)

-strip

strip symbols from the output (only in dual mode programs)

-nosyscalls

the output should not import RSXNT.DLL

-print:

print most actions from ntbind

By default NTbind creates an output file with the same filename with the extensions ".exe". The default DOS stubfile is "dosstub.dos". This file prints a message "This programs requires Win32"  if you run it under DOS. If you build a console mode program and this program should also run under DOS you must defines the DOS stubfile "dosstub.rsx". To debug non-dual-mode programs with DEBNT you must use the dos stub file "dosstub.dbg".

Example:

ntbind myfile.emx

creates the output file "myfile.exe".


Build Win32 Applications
Compiling Win32 Applications with GNU-C

This section describes how to compile your Win32 programs with GNU-C. To minimize the command line there is also a gcc compiler driver call gccnt.

Select your target:

Compiling a program with graphical user interface

Compiling a console-mode program

Compiling a DLL

Using GCCNT and DEBNT

There are two main libraries in \RSXNT\LIB:

NT1.A :

You should always link this library to your application. Otherwise you get the normal DOS and OS/2 file.

NT2.A :

Includes Win32 calls to Windows (User, Gdi, Kernel). For any Windows call you must link this library to your application.


Compiling GUI programs
Compiling a GUI program

>> Sample Code: \rsxnt\sample\speed

>> Sample Code: \rsxnt\sample\cplus

1 - Compile to object format:

gcc -c -ZC++-comments testgui.c

note: Win32-header files contains C++ statements. If you compile standard C-files you must use the option "-ZC++-comments"

C++ command:

gcc -c testgui.cc

2 - Link with Win32 Libraries:

gcc -o testgui.emx testgui.o -lnt1 -lnt2

note: nt1 and nt2 are the Win32 libraries

You can run step 1 and step 2 together:

gcc -ZC++-comments -o testgui.emx testgui.c -lnt1 -lnt2

3 - Convert this file to Win32

ntbind testgui.emx

note: ntbind creates the executable 'testwin.exe'. If ntbind found the function "WinMain" it creates GUI programs.

If your program uses resources:

>> Sample Code: \rsxnt\sample\sol

>> Sample Code: \rsxnt\sample\enumw

4 - Run resource compiler

rc -r testgui.rc

rc testgui.res testgui.exe


Compiling console-mode programs
Compiling a console-mode program:

Compiling console mode programs with Win32 functions:

>> Sample Code: \rsxnt\sample\console

If you use Win32 functions the compiler statements are equal to the section 'compiling GUI programs'.

1) Compile to object format:

gcc -c -ZC++-comments testcon.c

2 - Link with Win32 Libraries:

gcc -o testcon.emx testcon.o -lnt1 -lnt2

3 - Convert this file to Win32

ntbind testcon.emx

Compiling console mode programs without Win32 functions:

>> Sample Code: \rsxnt\sample\console

Without Win32 function, you can build dual-mode programs. This programs can also run under DOS.

You only need to relink your old programs.

1 - Compile to object format:

gcc -c testcon.c

2 - Link with Win32 Libraries:

gcc -o testcon.emx testcon.o -lnt1

note: if you forget to include the nt1 library, you will create only a DOS application

3 - Convert this file to Win32

ntbind testcon.emx -s c:\rsxnt\bin\dosstub.rsx

note: "dosstub.rsx" enable the automatic start of the emx or rsx dos extender if you run "testcon.exe" under DOS.


Compiling a DLL

>> Sample Code: \rsxnt\sample\dll

1 - Compile to object format

gcc -c -ZC++-comments testwin.c

note: Win32-header files contains C++ statements. If you compile standard C-files you must use the option "-ZC++-comments"

2 - link with Win32 Libraries

gcc -Zdll -o testwin.out testwin.o -lnt1 -lnt2

note: the option '-Zdll' must be used for creating DLL's.

3 - convert to a Win32

ntbind -o mydll.dll mydll.out [-nosyscall]

The options '-nosyscall' defines that you don't need any RSXNT.DLL function. This is useful to build a standalone DLL without any I/O functions.

You can run the program 'Syscall' to check you DLL about syscalls:

SYSCALL program:

Syntax:

syscall compiler-output-file

Expected Output:

No syscall function used

You can build the DLL with '-nosyscall'

If your DLL needs the RSXNT import, the output seems like:

Syscall used :               __exit

Syscall used :        __emx_version

Syscall used :             __remove

Syscall used :         __os_version

Syscall used :              __write

Syscall used :             __ioctl2

Syscall used :               __sbrk


The driver GCCNT
Using GCCNT and DEBNT

The program gccnt minimize the compiler options (libraries and ntbind). The first input file is the name of the executable. Otherwise you must use the GCC option "-o".

Usage:

GCCNT [-mode] [-others] gcc-arguments

mode options:

-dual:	executable for Win32 and DOS

-dll:	creates DLL

-gui:	default: GUI application if NTBind finds WinMain()

-cui:	default: CUI application if NTBind does not find WinMain()

others:

-defbase:	set base address to win32 default (disables -dual, but faster loading)

-debug:	don't strip symbols (default only for dual-mode)

-strip:	strip symbols (that are in dual-mode programs)

Examples:

GCCNT -dual prog.c prog1.c prog2.c

Creates a dual-mode program proc.exe for Win32 and DOS

GCCNT winapp.c -O2

Creates a GUI/CUI program winapp.exe with the GCC option "-O2"

GCCNT file1.c file2.c file3.c -o winapp.exe

Creates a GUI/CUI program winapp.exe (depends of WinMain)

Debugging with DEBNT:

The main tool that is missing in this release is a converter from old a.out to coff symbols. Then you can debug with a commercial debugger.

Warning: DEBNT is only for debugging console-mode programs. There are problems with GUI programs. You should include ansi.sys in your config.sys to get colors in the output. You must also the environment "TERM=ansi"

Debug switches:

You must use the switch "-debug".

Example:

gccnt -dual -debug rshell.c rshell1.c -g

debnt rshell.exe

Output from debugger:

C:\RSXNT\SAMPLE\DUAL>debnt rshell.exe

child PID 3

debugging file rshell.exe

GNUAOUT HEADER

text   = 00007000

data   = 00001000

bss    = 00001440

entry  = 00410000

syms   = 00003864

eip=00410000 eflags=00000a86

eax=00410000 ebx=005c0000 ecx=0061ff68 edx=bffc2a10

esp=0061fe3c ebp=0061ff78 esi=81530ff0 edi=8153133c

cs=0137 ds=013f es=013f ss=013f

__text():

00410000: 6800004200     push    __data

cmd:

First command:

cmd:go main

_main() (rshell.c#319): {

00410dd0: 55             push    ebp

cmd:list

_main() (rshell.c#319): {

00410dd0: 55             push    ebp

00410dd1: 89e5           mov     ebp,esp

00410dd3: 81ec04030000   sub     esp,0x304

00410dd9: e83e0a0000     call    ___main

#323:     signal(SIGCLD, signal_handler);

00410dde: 68200d4100     push    _signal_handler

00410de3: 6a12           push    18

00410de5: e8760d0000     call    _signal

00410dea: 83c408         add     esp,8

#324:     signal(SIGINT, signal_handler);

00410ded: 68200d4100     push    _signal_handler

00410df2: 6a02           push    2

cmd:

Help:

cmd:help

go <v>       g - go or continue execution

cont <v>     c - continue execution

step         s - step through instruction

next         n - step to next instruction

list <v>     l - list instructions at <v>

dump <v>     d - dump memory at <v>

disp v         - display symbol v

reg <m> <v>  r - show/set registers

where        w - display list of active functions

find         f - find a symbol/location (wildcard)

bp v           - set breakpoint at v

bx no          - x=List/Clear/Dis-/Enable breakpoint no

set m v <s>    - memory to value; size=byte/word

process        - show process data

sel s <n>      - show n selectors start with s

shell argv     - execute other program

quit         q - terminate debugger

help         ? - this text


The Gnu-C Win32 library
Creating Import Libraries:

>> Sample Code: \rsxnt\sample\dll

Every Windows function needs a "stdcall" frame to call the Windows DLLs. Here comes the tool 'makelib' to build these frames without writing this code.

makelib creates library files.

syntax:

makelib DllName.dll Win32IncludeFile.h [LibraryName]

makelib DllName.dll ImportDescription.imp [LibraryName]

example:

makelib comdlg32.dll commdlg.h comdlg32.a

Makelib needs information about the parameters.

If the second argument is a header file, makelib will search for "WINAPI" functions and counts the parameters.

Also it is possible to use a import description file. This file must have two colons every line:

first_function n

second_function n

"n" are the stackparameters

Example file (all Kernel, User and GDI calls): \RSXNT\LIB\NT.IMP

The tool Header takes an include file and writes the description file to the standard output. If makelib does an error, you can check the bug with the Header tool.


Porting to Win32
Porting Win32 sourcefiles to GNU-C

Include <WINGNUC.H> at the beginning of your file

The GNU-C compiler can't include the original "Windows.h" header file. This file isn't really a ANSI-C compatible file. You must include "WinGnuC.h" before "Windows.h". This makes the compiler happy.

Example:

#ifdef __GNUC__	/* make other compilers happy */

#include "wingnuc.h"

#endif

#include "windows.h"

#include "<stdlib.h>

...

Using _stdcall in callback functions (WINAPI, CALLBACK or EXPORT)

The GNU-C compiler does not know the statement "_stdcall" (MS extension). You must include a special macro in your source files. This macro emulates the "_stdcall" statement.

There are three macros, but they all define the same thing:

RETURN_CALLBACK( ARGS )

RETURN_EXPORT( ARGS )

RETURN_WINAPI( ARGS )

You must define these macros with the correct number of arguments. This statement should follow the "_stdcall" function.

You should define these macros in callbacks or exported functions.

Background:

The _stdcall keyword defines that the stack will be cleaned up from the called function. The function caller should not remove the stack. If you call a Window function like "MessageBox" the NT.A library contains a short code frame to handle the stack in the correct manner. But Windows can also call your code (callbacks). Here you must define these macors. The macro defines a command for NTBIND to patch the code at the end of the function.

Default C/C++ stack:

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

Caller	Function

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

PUSH ARGS

CALL Function

Begin function

Return

POP ARGS

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

_stdcall stack:

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

Caller	Function

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

PUSH ARGS

CALL Function

Begin function

Return (POP ARGS)

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

NTBIND patches the function return code to pop off the arguments.

Examples:

/* the standard window procedure */

LRESULT CALLBACK WndProc(

HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

  ....

your code

  ....

} RETURN_CALLBACK(4);

/* export procedure */

LONG EXPORT Maximum(LONG x, LONG y)

{

MessageBox(NULL, "Maximum called", " ", MB_OK);

return (x > y) ? x : z ;

} RETURN_EXPORT(2);

Loading a DLL and calling a DLL-functions:

>> Sample Code: \rsxnt\sample\ctl3d

>> Sample Code: \rsxnt\sample\dll

If you load a DLL via 'LoadLibrary' you should write a function caller.

This will cleanup the _stdcall stack.

example (\rsxnt\sample\ctl3d) :

/* this code try to register the ctl3d functions */

/* typedef for called functions */

typedef BOOL (WINAPI * CTL3D_FUNC) (HINSTANCE);

/* this is the function caller */

BOOL CallCtl3d(CTL3D_FUNC ctl3dfunc, HINSTANCE hInst)

{

    return (*ctl3dfunc) (hInstance);

}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nCmd)

{

    FARPROC lpfnDialog ;

    BOOL bCtl3d = FALSE;

    CTL3D_FUNC pRegister3d;

    CTL3D_FUNC pUnregister3d;

    CTL3D_FUNC pAutoSubclass3d;

    hCtl3d = LoadLibrary( "CTL3D32.DLL" );      // Get Handle

    if (hCtl3d) {

        pRegister3d = (CTL3D_FUNC)

                GetProcAddress( hCtl3d, "Ctl3dRegister" );

        pUnRegister3d = (CTL3D_FUNC)

                GetProcAddress( hCtl3d, "Ctl3dUnregister");

        pAutoSubclass3d = (CTL3D_FUNC)

                GetProcAddress( hCtl3d, "Ctl3dAutoSubclass");

        if ( !pRegister3d || !pUnRegister3d || !pAutoSubclass3d) {

            bCtl3d = FALSE;

        } else if (CallCtl3d(pRegister3d, hInst) == TRUE) {

            bCtl3d = TRUE;

            CallCtl3d(pAutoSubclass3d, hInst);

        }

    }

    lpfnDialog=MakeProcInstance(Dialog,hInst);

    DialogBox(hInst,(LPSTR)"DIALOG_1",NULL,lpfnDialog);

    FreeProcInstance(lpfnDialog);

    if (bCtl3d == TRUE)

        CallCtl3d(pUnRegister3d, hInst);

    return (FALSE);

}


Copyright
Copyright and runtime licence

Copyright:

RSXNT programs, libraries and sources

Copyright (c) by Rainer Schnitker 1995. All rights reserved.

You can distribute any library file in "\rsxnt\lib" with your application. You are allowed to change and copy the rsxnt library sources. If you improve the emx libraries, please send your enhancements to the author.

NTBIND.EXE and RSXNT.DLL 1.0 runtime licence:

NTBIND.EXE and RSXNT.DLL 1.0

Copyright (c) by Rainer Schnitker 1995. All rights reserved.

Terms for non-commercial use:

You are hereby permitted to use the NTBIND.EXE and RSXNT.DLL files with any and all non-commercial and non-shareware software programs free of any financial obligation to me, provided that if the program is distributed, it is distributed to the public, free of any charge for the program itself. There is no restriction on what kind of reselling of the above mentioned program is done (shareware houses, CD-ROMs, etc...), as long as the program is available to the public with no financial obligation to the author(s).

Licensing NTBIND.EXE and RSXNT.DLL 1.0 for commercial use:

If you wish to use NTBIND.EXE or RSXNT.DLL in a commercial, shareware, or any program which is to be sold or has attached to it an obligation to buy something, you MUST purchase a commercial distribution license. This license will allow royalty free distribution of one application using NTBIND.EXE and RSXNT.DLL. A separate license is required for each application in which NTBIND.EXE or RSXNT.DLL is used. A single licensed application may consist of more than one actual program, but all the programs within that application must be available only as part of the whole package and may not be sold separately for their own intrinsic value. The license fee is 40 DM (~= $29 U.S.) for a commercial or shareware program. Once purchased, this license is valid for the life of your program, including any and all major revisions.

There are some benefits you will receive by registering:

Minor updates for bugs

Help support

Q&A catalog

Send the file register.txt to the author.


Author
Author:

email to:

rainer@mathematik.uni-bielefeld.de

letters to:

Rainer Schnitker

Heeper Strasse 283

33607 Bielefeld

Germany

other RSX packages:

RSX (DPMIGCC):

DOS-extender for EMX files (Gcc, Emacs, TeX386)

RSXWIN:

Windows extender for EMX files (Gcc, Emacs, TeX386)

RSXWDK:

build & run 32-bit GNU-C WinApps for Win 3.1

ftp addresses:

Home server:

ftp: ftp.uni-bielefeld.de

dir: /pub/systems/ms-dos/misc

Also:

TeX servers (CTAN: Comprehensive TeX Achive Network)

Windows server (CICA)


RSX is a DPMI-compatible DOS-extender and is included in this package.

This program can run the EMX GNU-C compiler in a DOS-Box.

Click to the Author section


It is recommend to use EMX 0.9a.

Other versions are not tested with RSXNT.

Home ftp address:

ftp: ftp.uni-stuttgart.de [129.69.18.15]

dir: /pub/systems/os2/emx0.9a

Others: many OS/2 ftp server (hobbes-mirror)

ftp-os2.cdrom.com [192.153.46.2]

/os2/2_x/unix/emx09a

src.doc.ic.ac.uk [146.169.2.1]

/packages/os2/2_x/unix/emx09a

ftp.informatik.tu-muenchen.de [131.159.0.198]

/pub/comp/os/os2/gnu/emx+gcc

CD:

Hobbes OS/2 CD


1) you can't compile NT-SDK header files (error on C++ Comments)

2) compiler ignores #pragma pack() statement

2) the compiler can't write relocations in output file (bad for building a DLL)

3) bad Libraries, much work for Win32-compatible libraries.

4) no multithread libraries