
     Win32 PE executable with DJGPP GNU C/C++ compiller.

                Small description of utilites.

    Contents:
       How to install?
       DLL to .a convertor
       Make PE from COFF a.out


     The  software  described  in this document is destributed
under a GNU General Public License.

GNU software is Copyright by the Free Software Foundation.

DJGPP is Copyright by DJ Delorie.

Windows is a trademark of Microsoft Corporation.
Windows NT is a trademark of Microsoft Corporation.
Windows 2000 is a trademark of Microsoft Corporation.

     Other  product names mentioned in this description may be
trademarks   or  registered  trademarks  of  their  respective
companies and are hereby acknowledged.


                       How to install?

To install your need:

  1.Unpack arhive. E.g. type:

    pkunzip -p mfwpe11b.zip c:\djgpp

    (The good idea is to read this document up to end beforhand)
    Store "/lib/specs"  and rename "/lib/specs.pe" to "/lib/specs"

  2.Make  linkable  libraries (.a files) for Win32 API DLL.
As  rule  it's  nessesary  to  make  libraries for user32.dll,
kernel32.dll,  gdi32.dll.  As  well  frequently  advapi32.dll,
comdlg32.dll,  shell32.dll  are  nessesary  too. To use Socket
your  need  library for wsock32.dll, to use PlaySound function
your  need  winmm.dll,  etc.  To  make  library you can create
temporary  directory,  the  first,  is  good  idea,  but  it's
dispensable.  Change  curent directory to it and run dll2a.exe
for each DLL need you. E.g. type:

c:\>mkdir c:\lib_temp
c:\>cd c:\lib_temp
c:\lib_temp>dll2a.exe user32.dll
c:\lib_temp>ren user32.a c:\djgpp\lib\libuser.a

You can use next makefile and generate all automaticaly with DJGPP GNU MAKE.

#begin of 'makefile'

LIBDIR=$(DJDIR)/LIB/
DLLDIR=$(WINDIR)/SYSTEM/
# For Windows NT or 2000 DLLDIR must by DLLDIR=$(WINDIR)/SYSTEM32/
# WINDIR -- predefined Windows enviroment variable
# DJDIR --  DJGPP enviroment variable, must be defined in DJGPP.ENV

lib: libuser.a libuser.a libkern.a libgdi.a libshell.a libwadv.a lwinmm.a lwinmm.a lcdlg.a

libuser.a: user32.dll
        dll2s.exe -o $@  $<

libkern.a: %(DLLDIR)kernel32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libgdi.a: %(DLLDIR)gdi32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libshell.a: %(DLLDIR)shell32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libwadv.a: %(DLLDIR)advapi32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libwinmm.a: %(DLLDIR)winmm.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libcdlg.a: %(DLLDIR)comdlg32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

libwsock.a: %(DLLDIR)wsock32.dll
        dll2s.exe -o $(LIBDIR)$@  $<

#end of 'makefile'


     It  borrows  some time, because for each function in each
library assembler file will be created, exec "as.exe" and exec
"ar.exe".  Up  to  ten  minuit per library for big library and
slow machin.

     3.  At  last  you  must  customize your "specs" file to run
make_pe.exe  to  convert  a.out to Win32 PE. By default arhive
contents  valid  "specs"  file, and by default it replase that
file  in  DJGPP\LIB directory, but any GCC newer then 2.8 find
this  file  in DJGPP\LIB\GCC-LIB\DJGPP\2.952 for GNU C++ 2.952
or  DJGPP\LIB\GCC-LIB\DJGPP\EGCS-291.66  for EGCS C++ 2.91.66,
etc.  I  don't  know, what version you use, I thing it's not a
problem  for you replase or update using file by your own. The
"specs" in my arhive add two key to GCC:
        -Zpe  -- to generate Win32 PE executable
        -Zcon -- used only with -Zpe to generate Win32 console
                 application.
You can define your own keys. To generate PE you must use
"djgppe.djl"  linker  script.  "*startfile"  for  PE  must  be
"crt0pe.o".  These  files are also present in my arhive and be
default placed to DJGPP\LIB.

     4.The  big trouble it is header files, and description of
API  functions.  It  is  part  of Microsoft Windows SDK, and I
can't  destribute  tham.  Now  you  can  found  these files in
diferent  location.  It  is  included  in  any  other  Windows
compiller,  but  in  many case they doesn't directly compilled
with  GNU.  To  compile Microsoft's header with GNU compiller,
easy  changes  must  be  done.  In  the  begining  of the file
#define  __stdcall  __attribute__((stdcall)) must be inserted.
In  some  case you must edit Microsoft's function declaration,
move "PASCAL" to the end of declaration. E.g. if in SDK header
present:

    struct hostent* PASCAL gethostbyname(const char* name);

        you must make:

    struct hostent* gethostbyname(const char* name) PASCAL;

     If  you have nothing, use header's generated by DLL2S. In
this  case  you  must  edit  these  files,  insert argument in
declaration  of  each  function  or  use "gw_api.h". This file
contents next definetion:

    inline void PUSH(int a){ asm volatile("pushl %0;": :"g" (a) );};
    inline void PUSH(void* a){ asm volatile("pushl %0;": :"g" (a) );};

    #define API1(f,a)  ( PUSH(a),f())
    #define API2(f,a1,a2)  ( PUSH(a2),PUSH(a1),f())
    ...

    And you can call to API e.g. this way:


           #include "gw_api.h"
    extern "C" {
           #include <user32.h>
           #include <kernel32.h>
               };
        ...
       API4( MessageBox, 0, &"Hello world !",&"Test",  0);

     Warning!  In  this  case  you must use optimisation (keys
-O1,  -O2,  -O#),  otherwise  GNU  compiller  generate  inline
function  as no inline, and PUSH failure. In this case you can
use  #define  instead  inline. This might be use only with GNU
2.8x or older.

                     DLL to .a convertor

     This  program  read  incomming  DLL-file,  get  names  of
functions from it, and for each function:
  generate easy assembler file;
  exec "as.exe" to compile this file;
  exec "ar.exe" to add this file to output library;
  add incomplete declaration of function to output header file.
At the last header file is stored.
Command line have next format:
dll2s.exe {[-keys]}[-o out_file_name][-n filename] file.dll
Next option's keys supported:

    -s -- store assembler source, otherwise temporary assembler
          files are deleted.
    -a -- generate one AT&T assembler file only.
    -i -- generate one Intel assembler file only.
    -u -- add "unnamed" functions. Some DLL-functions could
have no name. It might be linked by number. Program also could
add these functions to the library, but what's the reason ?
    -l -- always  use  number  for  link.  Default  name of
          function  is  used, so it's possible. It is
          calculable. To use number you must overwrite startup
          file "crt0pe.o".
    -d -- no generate header file.
    -j -- store objects, otherwise temporary objects files are
          deleted.
    -n -- name for assembler file.
    -r -- generate header file only
    -f -- no generate #define  for A-function. All Windows API
          functions  that  recive string as argument have ASCI
          and  UNICODE versions. Usually one DLL contents both
          functions.  The  last  symbol  in  the  name of ASCI
          version  is  'A'.  The  last  symbol  in the name of
          UNICODE  version  is  'W'. By default, for each ASCI
          function  DLL2S  add  to  header  file  #define that
          define name without last 'A' as name with 'A'.

                   Make PE from COFF a.out

     This  program  only  adds  DOS  stub and first part of PE
header. Command line have next format:

make_pe [-c][-s Stack_Reserve_Size][-p Heap_Reserve_Size][-o out_file] input_file

Next option's keys supported:

    -c -- to generate Win32 console application.
    -s -- to define Stack Reserve Size. By default it is 64 Kb.
    -p -- to define Heap Reserve Size. By default it is 1 Mb.
    -o -- to define name of output file.

     This  program  always  setup  Commit Heap Size and Commit
Stack  Size  to  4  Kb. Program will not use more memory until
program  doesn't  requist  it. This program could convert only
specifed  COFF  files,  that  begin  from  the last part of PE
header.  This  part  is  precent  in the "crt0pe.o" -- startup
file.  It must be linked the first. It defines in "djgppe.djl"
-- linker script.

                                                 M. Feoktistov

