[ros-kernel] how to search several PE files to see if any of them import a particular function?

jeanmichel.123 at free.fr jeanmichel.123 at free.fr
Wed Nov 12 14:58:39 CET 2003


It is not a direct answer, but I wanted to do somethin like this.

I used the pedump from rosapps and make modification int it.

It was direct reading of the file to printf symbols on stdout.

I have introduced a cpp layer, which should allow easy using of symbols.

However the actual behaviour of dll_symbols is about the same as pedump.

The attached files should be copied in rosapps/sysutils.

Note: I did this because I cannot test kbdfr, because I don't have reactos, 
because I have NTFS... :-( .


> > Is there a way to do this?
> >
> > I want to use it on various PE files (DLLs, EXEs etc) to see if any of 
> > them import some of the functions for which I dont yet have a 
> > prototype :)
-------------- next part --------------
# $Id: makefile,v 1.14 2003/06/27 21:17:35 gvg Exp $
#
# ReactOS System Utilities
#
# 1999-02-16 (Emanuele Aliberti)
#	Added chkdskx.c and formatx.c by Mark Russinovich
#	(mark at sysinternals.com) and shutdown.c
#
# 1999-03-03 (Emanuele Aliberti)
#	Added login.c and chklib.c
#
# 1999-03-16 (Emanuele Aliberti)
#	Added regnav.c
#
# 1999-12-19 (ea)
#	Added qsi.c
#
# 2000-04-23 (ea)
#	Added pedump.c
#
# 2000-08-4 (ea)
#	Added ldd.c; removed login.c
#
#
PATH_TO_TOP=..
PATH_TO_CVSROOT=../$(PATH_TO_TOP)

BASE_CFLAGS = -I$(PATH_TO_CVSROOT)/reactos/include -D_M_IX86


ROS_DIR=$(PATH_TO_CVSROOT)/reactos
ROS_INC=$(ROS_DIR)/include
ROS_LIB=$(ROS_DIR)/dk/w32/lib
IMPORT_NTDLL=$(ROS_LIB)/ntdll.a
IMPORT_FMIFS=$(ROS_LIB)/fmifs.a
IMPORT_KERNEL32=$(ROS_LIB)/kernel32.a
IMPORT_ADVAPI32=$(ROS_LIB)/advapi32.a
IMPORT_USER32=$(ROS_LIB)/user32.a
IMPORT_MSVCRT=

TARGET=\
	chklib.exe \
	ldd.exe \
	pedump.exe \
	dll_symbols.exe \
	shutdown.exe \
	chkdsk.exe \
	format.exe 

# Removed due to dependance on C++ compiler
#
#	regexpl/regexpl.exe
#

all: $(TARGET)


# By Mark Russinovich

chkdsk.exe: chkdsk.o win32err.o wmain.o chkdsk.coff
	$(CC) \
		chkdsk.o	\
		win32err.o		\
		wmain.o			\
		chkdsk.coff		\
		$(IMPORT_FMIFS)		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
		-o chkdsk.exe 
	$(NM) --numeric-sort chkdsk.exe > chkdsk.sym

format.exe: format.o win32err.o wmain.o format.coff
	$(CC) \
		format.o		\
		win32err.o		\
		wmain.o			\
		format.coff		\
		$(IMPORT_FMIFS)		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
		-o format.exe
	$(NM) --numeric-sort format.exe > format.sym

#---

chklib.exe: chklib.o win32err.o chklib.coff
	$(CC) \
		chklib.o		\
		win32err.o		\
		chklib.coff		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
		-o chklib.exe
	$(NM) --numeric-sort chklib.exe > chklib.sym


shutdown.exe: shutdown.o win32err.o shutdown.coff
	$(CC) \
		shutdown.o		\
		win32err.o		\
		shutdown.coff		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_USER32)	\
		$(IMPORT_MSVCRT)	\
		-o shutdown.exe
	$(NM) --numeric-sort shutdown.exe > shutdown.sym

pedump.exe: pedump.o pedump.coff
	$(CC) \
		pedump.o		\
		pedump.coff		\
		$(IMPORT_NTDLL)		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
		-o pedump.exe
	$(NM) --numeric-sort pedump.exe > pedump.sym

pedump.o: pedump.c

dll_symbols.exe: dll_symbols.o 
	$(CC) \
		dll_symbols.o		\
		$(IMPORT_NTDLL)		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
                d:\rostools\MinGw\lib\libstdc++.a \
		-o dll_symbols.exe
	$(NM) --numeric-sort dll_symbols.exe > dll_symbols.sym

dll_symbols.o: dll_symbols.cpp

#		dll_symbols.coff		\


ldd.exe: ldd.o win32err.o ldd.coff
	$(CC) \
		ldd.o			\
		win32err.o		\
		ldd.coff		\
		$(IMPORT_KERNEL32)	\
		$(IMPORT_MSVCRT)	\
		-o ldd.exe
	$(NM) --numeric-sort ldd.exe > ldd.sym

ldd.o: ldd.c

# By Nedko Arnaoudov

regexpl/regexpl.exe:
	make -C regexpl

#---

install:

.phony: install

CLEAN_FILES = *.o *.exe *.sym

clean: $(CLEAN_FILES:%=%_clean)

$(CLEAN_FILES:%=%_clean): %_clean:
	- $(RM) $*

.phony: clean $(CLEAN_FILES:%=%_clean)


floppy: $(TARGET:%=$(FLOPPY_DIR)/apps/%)

$(TARGET:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
	$(CP) $* $(FLOPPY_DIR)\apps\$*
else
	$(CP) $* $(FLOPPY_DIR)/apps/$*
endif


dist: $(TARGET:%=../$(DIST_DIR)/apps/%)

$(TARGET:%=../$(DIST_DIR)/apps/%): ../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
	$(CP) $* ..\$(DIST_DIR)\apps\$*
else
	$(CP) $* ../$(DIST_DIR)/apps/$*
endif
	
include ../rules.mak
	
# EOF
-------------- next part --------------
// $Id: pedump.c,v 1.1 2001/01/13 18:19:23 ea Exp $
//
// This program was written by Sang Cho, assistant professor at 
//                                       the department of 
//                                                                               computer science and engineering
//                                                                               chongju university
// this program is based on the program pefile.c
// which is written by Randy Kath(Microsoft Developmer Network Technology Group)
// in june 12, 1993.
// I have investigated P.E. file format as thoroughly as possible,
// but I cannot claim that I am an expert yet, so some of its information  
// may give you wrong results.
//
//
//
// language used: djgpp
// date of creation: September 28, 1997
//
// date of first release: October 15, 1997
//
//
//      you can contact me: e-mail address: sangcho at alpha94.chongju.ac.kr
//                            hitel id: chokhas
//                        phone number: (0431) 229-8491    +82-431-229-8491
//
//
//
//   Copyright (C) 1997.                                 by Sang Cho.
//
//   Permission is granted to make and distribute verbatim copies of this
// program provided the copyright notice and this permission notice are
// preserved on all copies.
//
//
// File: pedump.c ( I included header file into source file. )
//
// LICENSE
//      Sources released under GNU General Public License version 2
//      or later by Mr. Sang Cho permission.
//
// REVISIONS
//      2000-04-23 (ea) Initial adaptation to GCC/MinGW/ROS.
//      2000-08-05 (ea) Initial raw adaptation done.
//


#include <string>
#include <map>
#include <iostream>



//#include <stdio.h>
//#include <stdarg.h>
//#include <string.h>
//#include <setjmp.h>
#include <malloc.h>

#ifndef bcopy
#define bcopy(s,d,z) memcpy((d),(s),(z))
#endif

typedef char CHAR;
typedef short WCHAR;
typedef short SHORT;
typedef long LONG;
typedef unsigned short USHORT;
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef BYTE *PBYTE;
typedef WORD *PWORD;
typedef DWORD *PDWORD;
typedef void *LPVOID;
typedef int boolean;

#define VOID                void
#define BOOLEAN             boolean

#ifndef NULL
#define NULL                0
#endif

#define FALSE               0
#define TRUE                1
#define CONST               const
#define LOWORD(l)           ((WORD)(l))
#define WINAPI		__stdcall

//
// Image Format
//

#define IMAGE_DOS_SIGNATURE                 0x5A4D	// MZ
#define IMAGE_OS2_SIGNATURE                 0x454E	// NE
#define IMAGE_OS2_SIGNATURE_LE              0x454C	// LE
#define IMAGE_VXD_SIGNATURE                 0x454C	// LE
#define IMAGE_NT_SIGNATURE                  0x00004550	// PE00

typedef struct _IMAGE_DOS_HEADER
  {				// DOS .EXE header

    WORD e_magic;		// Magic number

    WORD e_cblp;		// Bytes on last page of file

    WORD e_cp;			// Pages in file

    WORD e_crlc;		// Relocations

    WORD e_cparhdr;		// Size of header in paragraphs

    WORD e_minalloc;		// Minimum extra paragraphs needed

    WORD e_maxalloc;		// Maximum extra paragraphs needed

    WORD e_ss;			// Initial (relative) SS value

    WORD e_sp;			// Initial SP value

    WORD e_csum;		// Checksum

    WORD e_ip;			// Initial IP value

    WORD e_cs;			// Initial (relative) CS value

    WORD e_lfarlc;		// File address of relocation table

    WORD e_ovno;		// Overlay number

    WORD e_res[4];		// Reserved words

    WORD e_oemid;		// OEM identifier (for e_oeminfo)

    WORD e_oeminfo;		// OEM information; e_oemid specific

    WORD e_res2[10];		// Reserved words

    LONG e_lfanew;		// File address of new exe header

  }
IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

//
// File header format.
//



typedef struct _IMAGE_FILE_HEADER
  {
    WORD Machine;
    WORD NumberOfSections;
    DWORD TimeDateStamp;
    DWORD PointerToSymbolTable;
    DWORD NumberOfSymbols;
    WORD SizeOfOptionalHeader;
    WORD Characteristics;
  }
IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

#define IMAGE_SIZEOF_FILE_HEADER             20

#define IMAGE_FILE_RELOCS_STRIPPED           0x0001	// Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002	// File is executable  (i.e. no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004	// Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED       0x0008	// Local symbols stripped from file.
#define IMAGE_FILE_BYTES_REVERSED_LO         0x0080	// Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE             0x0100	// 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED            0x0200	// Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400	// If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP         0x0800	// If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM                    0x1000	// System File.
#define IMAGE_FILE_DLL                       0x2000	// File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY            0x4000	// File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI         0x8000	// Bytes of machine word are reversed.

#define IMAGE_FILE_MACHINE_UNKNOWN           0
#define IMAGE_FILE_MACHINE_I386              0x14c	// Intel 386.
#define IMAGE_FILE_MACHINE_R3000             0x162	// MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000             0x166	// MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000            0x168	// MIPS little-endian
#define IMAGE_FILE_MACHINE_ALPHA             0x184	// Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC           0x1F0	// IBM PowerPC Little-Endian



//
// Directory format.
//

typedef struct _IMAGE_DATA_DIRECTORY
  {
    DWORD VirtualAddress;
    DWORD Size;

  }
IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

//
// Optional header format.
//

typedef struct _IMAGE_OPTIONAL_HEADER
  {
    //
    // Standard fields.
    //
    WORD Magic;
    BYTE MajorLinkerVersion;
    BYTE MinorLinkerVersion;
    DWORD SizeOfCode;
    DWORD SizeOfInitializedData;
    DWORD SizeOfUninitializedData;
    DWORD AddressOfEntryPoint;
    DWORD BaseOfCode;
    DWORD BaseOfData;

    //
    // NT additional fields.
    //

    DWORD ImageBase;
    DWORD SectionAlignment;
    DWORD FileAlignment;
    WORD MajorOperatingSystemVersion;
    WORD MinorOperatingSystemVersion;
    WORD MajorImageVersion;
    WORD MinorImageVersion;
    WORD MajorSubsystemVersion;
    WORD MinorSubsystemVersion;
    DWORD Win32VersionValue;
    DWORD SizeOfImage;
    DWORD SizeOfHeaders;
    DWORD CheckSum;
    WORD Subsystem;
    WORD DllCharacteristics;
    DWORD SizeOfStackReserve;
    DWORD SizeOfStackCommit;
    DWORD SizeOfHeapReserve;
    DWORD SizeOfHeapCommit;
    DWORD LoaderFlags;
    DWORD NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

  }
IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;


typedef struct _IMAGE_NT_HEADERS
  {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER OptionalHeader;

  }
IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;


// Directory Entries

#define IMAGE_DIRECTORY_ENTRY_EXPORT         0	// Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT         1	// Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2	// Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3	// Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY       4	// Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5	// Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG          6	// Debug Directory
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7	// Description String
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8	// Machine Value (MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_TLS            9	// TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10	// Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11	// Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT           12	// Import Address Table

//
// Section header format.
//

#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct _IMAGE_SECTION_HEADER
  {
    BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
    union
      {
	DWORD PhysicalAddress;
	DWORD VirtualSize;
      }
    Misc;
    DWORD VirtualAddress;
    DWORD SizeOfRawData;
    DWORD PointerToRawData;
    DWORD PointerToRelocations;
    DWORD PointerToLinenumbers;
    WORD NumberOfRelocations;
    WORD NumberOfLinenumbers;
    DWORD Characteristics;

  }
IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

#define IMAGE_SIZEOF_SECTION_HEADER          40


//
// Export Format
//

typedef struct _IMAGE_EXPORT_DIRECTORY
  {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Name;
    DWORD Base;
    DWORD NumberOfFunctions;
    DWORD NumberOfNames;
    PDWORD *AddressOfFunctions;
    PDWORD *AddressOfNames;
    PWORD *AddressOfNameOrdinals;

  }
IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

//
// Import Format
//

typedef struct _IMAGE_IMPORT_BY_NAME
  {
    WORD Hint;
    BYTE Name[1];

  }
IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

#define IMAGE_ORDINAL_FLAG 0x80000000
#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)


//
// Resource Format.
//

//
// Resource directory consists of two counts, following by a variable length
// array of directory entries.  The first count is the number of entries at
// beginning of the array that have actual names associated with each entry.
// The entries are in ascending order, case insensitive strings.  The second
// count is the number of entries that immediately follow the named entries.
// This second count identifies the number of entries that have 16-bit integer
// Ids as their name.  These entries are also sorted in ascending order.
//
// This structure allows fast lookup by either name or number, but for any
// given resource entry only one form of lookup is supported, not both.
// This is consistant with the syntax of the .RC file and the .RES file.
//

// Predefined resource types ... there may be some more, but I don't have
//                               the information yet.  .....sang cho.....

#define    RT_NEWRESOURCE   0x2000
#define    RT_ERROR         0x7fff
#define    RT_CURSOR        1
#define    RT_BITMAP        2
#define    RT_ICON          3
#define    RT_MENU          4
#define    RT_DIALOG        5
#define    RT_STRING        6
#define    RT_FONTDIR       7
#define    RT_FONT          8
#define    RT_ACCELERATORS  9
#define    RT_RCDATA        10
#define    RT_MESSAGETABLE  11
#define    RT_GROUP_CURSOR  12
#define    RT_GROUP_ICON    14
#define    RT_VERSION       16
#define    NEWBITMAP        (RT_BITMAP|RT_NEWRESOURCE)
#define    NEWMENU          (RT_MENU|RT_NEWRESOURCE)
#define    NEWDIALOG        (RT_DIALOG|RT_NEWRESOURCE)


typedef struct _IMAGE_RESOURCE_DIRECTORY
  {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    WORD NumberOfNamedEntries;
    WORD NumberOfIdEntries;
//      IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[1];

  }
IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;

#define IMAGE_RESOURCE_NAME_IS_STRING        0x80000000
#define IMAGE_RESOURCE_DATA_IS_DIRECTORY     0x80000000

//
// Each directory contains the 32-bit Name of the entry and an offset,
// relative to the beginning of the resource directory of the data associated
// with this directory entry.  If the name of the entry is an actual text
// string instead of an integer Id, then the high order bit of the name field
// is set to one and the low order 31-bits are an offset, relative to the
// beginning of the resource directory of the string, which is of type
// IMAGE_RESOURCE_DIRECTORY_STRING.  Otherwise the high bit is clear and the
// low-order 16-bits are the integer Id that identify this resource directory
// entry. If the directory entry is yet another resource directory (i.e. a
// subdirectory), then the high order bit of the offset field will be
// set to indicate this.  Otherwise the high bit is clear and the offset
// field points to a resource data entry.
//

typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY
  {
    DWORD Name;
    DWORD OffsetToData;

  }
IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;

//
// For resource directory entries that have actual string names, the Name
// field of the directory entry points to an object of the following type.
// All of these string objects are stored together after the last resource
// directory entry and before the first resource data object.  This minimizes
// the impact of these variable length objects on the alignment of the fixed
// size directory entry objects.
//

typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING
  {
    WORD Length;
    CHAR NameString[1];

  }
IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING;


typedef struct _IMAGE_RESOURCE_DIR_STRING_U
  {
    WORD Length;
    WCHAR NameString[1];

  }
IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;


//
// Each resource data entry describes a leaf node in the resource directory
// tree.  It contains an offset, relative to the beginning of the resource
// directory of the data for the resource, a size field that gives the number
// of bytes of data at that offset, a CodePage that should be used when
// decoding code point values within the resource data.  Typically for new
// applications the code page would be the unicode code page.
//

typedef struct _IMAGE_RESOURCE_DATA_ENTRY
  {
    DWORD OffsetToData;
    DWORD Size;
    DWORD CodePage;
    DWORD Reserved;

  }
IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;


//  Menu Resources       ... added by .....sang cho....

// Menu resources are composed of a menu header followed by a sequential list
// of menu items. There are two types of menu items: pop-ups and normal menu
// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with
// an empty name, zero ID, and zero flags.

typedef struct _IMAGE_MENU_HEADER
  {
    WORD wVersion;		// Currently zero

    WORD cbHeaderSize;		// Also zero

  }
IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER;

typedef struct _IMAGE_POPUP_MENU_ITEM
  {
    WORD fItemFlags;
    WCHAR szItemText[1];

  }
IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM;

typedef struct _IMAGE_NORMAL_MENU_ITEM
  {
    WORD fItemFlags;
    WORD wMenuID;
    WCHAR szItemText[1];

  }
IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM;

#define GRAYED       0x0001	// GRAYED keyword
#define INACTIVE     0x0002	// INACTIVE keyword
#define BITMAP       0x0004	// BITMAP keyword
#define OWNERDRAW    0x0100	// OWNERDRAW keyword
#define CHECKED      0x0008	// CHECKED keyword
#define POPUP        0x0010	// used internally
#define MENUBARBREAK 0x0020	// MENUBARBREAK keyword
#define MENUBREAK    0x0040	// MENUBREAK keyword
#define ENDMENU      0x0080	// used internally


// Dialog Box Resources .................. added by sang cho.

// A dialog box is contained in a single resource and has a header and 
// a portion repeated for each control in the dialog box.
// The item DWORD IStyle is a standard window style composed of flags found
// in WINDOWS.H.
// The default style for a dialog box is:
// WS_POPUP | WS_BORDER | WS_SYSMENU
// 
// The itme marked "Name or Ordinal" are :
// If the first word is an 0xffff, the next two bytes contain an ordinal ID.
// Otherwise, the first one or more WORDS contain a double-null-terminated string.
// An empty string is represented by a single WORD zero in the first location.
// 
// The WORD wPointSize and WCHAR szFontName entries are present if the FONT
// statement was included for the dialog box. This can be detected by checking
// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these
// entries will be present.

typedef struct _IMAGE_DIALOG_BOX_HEADER1
  {
    DWORD IStyle;
    DWORD IExtendedStyle;	// New for Windows NT

    WORD nControls;		// Number of Controls

    WORD x;
    WORD y;
    WORD cx;
    WORD cy;
//      N_OR_O MenuName;         // Name or Ordinal ID
    //      N_OR_O ClassName;                // Name or Ordinal ID
    //      WCHAR  szCaption[];
    //      WORD   wPointSize;       // Only here if FONT set for dialog
    //      WCHAR  szFontName[];     // This too
  }
IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER;

typedef union _NAME_OR_ORDINAL
  {				// Name or Ordinal ID

    struct _ORD_ID
      {
	WORD flgId;
	WORD Id;
      }
    ORD_ID;
    WCHAR szName[1];
  }
NAME_OR_ORDINAL, *PNAME_OR_ORDINAL;

// The data for each control starts on a DWORD boundary (which may require
// some padding from the previous control), and its format is as follows:

typedef struct _IMAGE_CONTROL_DATA
  {
    DWORD IStyle;
    DWORD IExtendedStyle;
    WORD x;
    WORD y;
    WORD cx;
    WORD cy;
    WORD wId;
//  N_OR_O  ClassId;
    //  N_OR_O  Text;
    //  WORD    nExtraStuff;
  }
IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA;

#define BUTTON       0x80
#define EDIT         0x81
#define STATIC       0x82
#define LISTBOX      0x83
#define SCROLLBAR    0x84
#define COMBOBOX     0x85

// The various statements used in a dialog script are all mapped to these
// classes along with certain modifying styles. The values for these styles
// can be found in WINDOWS.H. All dialog controls have the default styles
// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows:
//
// Statement           Default Class         Default Styles
// CONTROL             None                  WS_CHILD|WS_VISIBLE
// LTEXT               STATIC                ES_LEFT
// RTEXT               STATIC                ES_RIGHT
// CTEXT               STATIC                ES_CENTER
// LISTBOX             LISTBOX               WS_BORDER|LBS_NOTIFY
// CHECKBOX            BUTTON                BS_CHECKBOX|WS_TABSTOP
// PUSHBUTTON          BUTTON                BS_PUSHBUTTON|WS_TABSTOP
// GROUPBOX            BUTTON                BS_GROUPBOX
// DEFPUSHBUTTON       BUTTON                BS_DFPUSHBUTTON|WS_TABSTOP
// RADIOBUTTON         BUTTON                BS_RADIOBUTTON
// AUTOCHECKBOX        BUTTON                BS_AUTOCHECKBOX
// AUTO3STATE          BUTTON                BS_AUTO3STATE
// AUTORADIOBUTTON     BUTTON                BS_AUTORADIOBUTTON
// PUSHBOX             BUTTON                BS_PUSHBOX
// STATE3              BUTTON                BS_3STATE
// EDITTEXT            EDIT                  ES_LEFT|WS_BORDER|WS_TABSTOP
// COMBOBOX            COMBOBOX              None
// ICON                STATIC                SS_ICON
// SCROLLBAR           SCROLLBAR             None
///

#define WS_OVERLAPPED   0x00000000L
#define WS_POPUP        0x80000000L
#define WS_CHILD        0x40000000L
#define WS_CLIPSIBLINGS 0x04000000L
#define WS_CLIPCHILDREN 0x02000000L
#define WS_VISIBLE      0x10000000L
#define WS_DISABLED     0x08000000L
#define WS_MINIMIZE     0x20000000L
#define WS_MAXIMIZE     0x01000000L
#define WS_CAPTION      0x00C00000L
#define WS_BORDER       0x00800000L
#define WS_DLGFRAME     0x00400000L
#define WS_VSCROLL      0x00200000L
#define WS_HSCROLL      0x00100000L
#define WS_SYSMENU      0x00080000L
#define WS_THICKFRAME   0x00040000L
#define WS_MINIMIZEBOX  0x00020000L
#define WS_MAXIMIZEBOX  0x00010000L
#define WS_GROUP        0x00020000L
#define WS_TABSTOP      0x00010000L

// other aliases
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
#define WS_POPUPWINDOW  (WS_POPUP | WS_BORDER | WS_SYSMENU)
#define WS_CHILDWINDOW  (WS_CHILD)
#define WS_TILED        WS_OVERLAPPED
#define WS_ICONIC       WS_MINIMIZE
#define WS_SIZEBOX      WS_THICKFRAME
#define WS_TILEDWINDOW  WS_OVERLAPPEDWINDOW

#define WS_EX_DLGMODALFRAME     0x00000001L
#define WS_EX_NOPARENTNOTIFY    0x00000004L
#define WS_EX_TOPMOST           0x00000008L
#define WS_EX_ACCEPTFILES       0x00000010L
#define WS_EX_TRANSPARENT       0x00000020L

#define BS_PUSHBUTTON           0x00000000L
#define BS_DEFPUSHBUTTON        0x00000001L
#define BS_CHECKBOX             0x00000002L
#define BS_AUTOCHECKBOX         0x00000003L
#define BS_RADIOBUTTON          0x00000004L
#define BS_3STATE               0x00000005L
#define BS_AUTO3STATE           0x00000006L
#define BS_GROUPBOX             0x00000007L
#define BS_USERBUTTON           0x00000008L
#define BS_AUTORADIOBUTTON      0x00000009L
#define BS_OWNERDRAW            0x0000000BL
#define BS_LEFTTEXT             0x00000020L

#define ES_LEFT         0x00000000L
#define ES_CENTER       0x00000001L
#define ES_RIGHT        0x00000002L
#define ES_MULTILINE    0x00000004L
#define ES_UPPERCASE    0x00000008L
#define ES_LOWERCASE    0x00000010L
#define ES_PASSWORD     0x00000020L
#define ES_AUTOVSCROLL  0x00000040L
#define ES_AUTOHSCROLL  0x00000080L
#define ES_NOHIDESEL    0x00000100L
#define ES_OEMCONVERT   0x00000400L
#define ES_READONLY     0x00000800L
#define ES_WANTRETURN   0x00001000L

#define LBS_NOTIFY            0x0001L
#define LBS_SORT              0x0002L
#define LBS_NOREDRAW          0x0004L
#define LBS_MULTIPLESEL       0x0008L
#define LBS_OWNERDRAWFIXED    0x0010L
#define LBS_OWNERDRAWVARIABLE 0x0020L
#define LBS_HASSTRINGS        0x0040L
#define LBS_USETABSTOPS       0x0080L
#define LBS_NOINTEGRALHEIGHT  0x0100L
#define LBS_MULTICOLUMN       0x0200L
#define LBS_WANTKEYBOARDINPUT 0x0400L
#define LBS_EXTENDEDSEL       0x0800L
#define LBS_DISABLENOSCROLL   0x1000L

#define SS_LEFT             0x00000000L
#define SS_CENTER           0x00000001L
#define SS_RIGHT            0x00000002L
#define SS_ICON             0x00000003L
#define SS_BLACKRECT        0x00000004L
#define SS_GRAYRECT         0x00000005L
#define SS_WHITERECT        0x00000006L
#define SS_BLACKFRAME       0x00000007L
#define SS_GRAYFRAME        0x00000008L
#define SS_WHITEFRAME       0x00000009L
#define SS_SIMPLE           0x0000000BL
#define SS_LEFTNOWORDWRAP   0x0000000CL
#define SS_BITMAP           0x0000000EL

//
// Debug Format
//

typedef struct _IMAGE_DEBUG_DIRECTORY
  {
    DWORD Characteristics;
    DWORD TimeDateStamp;
    WORD MajorVersion;
    WORD MinorVersion;
    DWORD Type;
    DWORD SizeOfData;
    DWORD AddressOfRawData;
    DWORD PointerToRawData;
  }
IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;

#define IMAGE_DEBUG_TYPE_UNKNOWN          0
#define IMAGE_DEBUG_TYPE_COFF             1
#define IMAGE_DEBUG_TYPE_CODEVIEW         2
#define IMAGE_DEBUG_TYPE_FPO              3
#define IMAGE_DEBUG_TYPE_MISC             4
#define IMAGE_DEBUG_TYPE_EXCEPTION        5
#define IMAGE_DEBUG_TYPE_FIXUP            6
#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC      7
#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC    8


typedef struct _IMAGE_DEBUG_MISC
  {
    DWORD DataType;		// type of misc data, see defines

    DWORD Length;		// total length of record, rounded to four
    // byte multiple.

    BOOLEAN Unicode;		// TRUE if data is unicode string

    BYTE Reserved[3];
    BYTE Data[1];		// Actual data

  }
IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;


//
// Debugging information can be stripped from an image file and placed
// in a separate .DBG file, whose file name part is the same as the
// image file name part (e.g. symbols for CMD.EXE could be stripped
// and placed in CMD.DBG).  This is indicated by the IMAGE_FILE_DEBUG_STRIPPED
// flag in the Characteristics field of the file header.  The beginning of
// the .DBG file contains the following structure which captures certain
// information from the image file.  This allows a debug to proceed even if
// the original image file is not accessable.  This header is followed by
// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more
// IMAGE_DEBUG_DIRECTORY structures.  The latter structures and those in
// the image file contain file offsets relative to the beginning of the
// .DBG file.
//
// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure
// is left in the image file, but not mapped.  This allows a debugger to
// compute the name of the .DBG file, from the name of the image in the
// IMAGE_DEBUG_MISC structure.
//

typedef struct _IMAGE_SEPARATE_DEBUG_HEADER
  {
    WORD Signature;
    WORD Flags;
    WORD Machine;
    WORD Characteristics;
    DWORD TimeDateStamp;
    DWORD CheckSum;
    DWORD ImageBase;
    DWORD SizeOfImage;
    DWORD NumberOfSections;
    DWORD ExportedNamesSize;
    DWORD DebugDirectorySize;
    DWORD SectionAlignment;
    DWORD Reserved[2];
  }
IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;

#define IMAGE_SEPARATE_DEBUG_SIGNATURE  0x4944

#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000
#define IMAGE_SEPARATE_DEBUG_MISMATCH   0x8000	// when DBG was updated, the
						// old checksum didn't match.


//
// End Image Format
//


#define SIZE_OF_NT_SIGNATURE	sizeof (DWORD)
#define MAXRESOURCENAME 	13

/* global macros to define header offsets into file */
/* offset to PE file signature                                 */
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a		     +	\
			((PIMAGE_DOS_HEADER)a)->e_lfanew))

/* DOS header identifies the NT PEFile signature dword
   the PEFILE header exists just after that dword              */
#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE))

/* PE optional header is immediately after PEFile header       */
#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE		     +	\
			 sizeof (IMAGE_FILE_HEADER)))

/* section headers are immediately after PE optional header    */
#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE		     +	\
			 sizeof (IMAGE_FILE_HEADER)	     +	\
			 sizeof (IMAGE_OPTIONAL_HEADER)))


typedef struct //tagImportDirectory
  {
    DWORD dwRVAFunctionNameList;
    DWORD dwUseless1;
    DWORD dwUseless2;
    DWORD dwRVAModuleName;
    DWORD dwRVAFunctionAddressList;
  }
IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;


/* global prototypes for functions in pefile.c */
/* PE file header info */
BOOL WINAPI GetDosHeader (LPVOID, PIMAGE_DOS_HEADER);
DWORD WINAPI ImageFileType (LPVOID);
BOOL WINAPI GetPEFileHeader (LPVOID, PIMAGE_FILE_HEADER);

/* PE optional header info */
BOOL WINAPI GetPEOptionalHeader (LPVOID, PIMAGE_OPTIONAL_HEADER);
LPVOID WINAPI GetModuleEntryPoint (LPVOID);
int WINAPI NumOfSections (LPVOID);
LPVOID WINAPI GetImageBase (LPVOID);
LPVOID WINAPI ImageDirectoryOffset (LPVOID, DWORD);
LPVOID WINAPI ImageDirectorySection (LPVOID, DWORD);

/* PE section header info */
//int   WINAPI GetSectionNames (LPVOID, HANDLE, char **);
int WINAPI GetSectionNames (LPVOID, char **);
BOOL WINAPI GetSectionHdrByName (LPVOID, PIMAGE_SECTION_HEADER, char *);

//
// structur to store string tokens
//
typedef struct _Str_P
  {
    char flag;			// string_flag '@' or '%' or '#'

    char *pos;			// starting postion of string

    int length;			// length of string

    BOOL wasString;		// if it were stringMode or not

  }
Str_P;

/* import section info */
int WINAPI GetImportModuleNames (LPVOID, char **);
int WINAPI GetImportFunctionNamesByIndex (LPVOID, int index, char **);

// import function name reporting
int WINAPI GetStringLength (char *);
void WINAPI GetPreviousParamString (char *, char *);
void WINAPI TranslateParameters (char **, char **, char **);
BOOL WINAPI StringExpands (char **, char **, char **, Str_P *);
LPVOID WINAPI TranslateFunctionName (char *);

/* export section info */
int WINAPI GetExportFunctionNames (LPVOID, char **);

/* resource section info */
#if 0
int WINAPI GetNumberOfResources (LPVOID);
int WINAPI GetListOfResourceTypes (LPVOID, char **);
int WINAPI MenuScan (int *, WORD **);
int WINAPI MenuFill (char **, WORD **);
void WINAPI StrangeMenuFill (char **, WORD **, int);
int WINAPI GetContentsOfMenu (LPVOID, char **);
int WINAPI PrintMenu (int, char **);
int WINAPI PrintStrangeMenu (char **);
int WINAPI dumpMenu (char **psz, int size);
#endif

/* debug section info */
BOOL WINAPI IsDebugInfoStripped (LPVOID);
int WINAPI RetrieveModuleName (LPVOID, char **);
BOOL WINAPI IsDebugFile (LPVOID);
BOOL WINAPI GetSeparateDebugHeader (LPVOID, PIMAGE_SEPARATE_DEBUG_HEADER);


/**********************************************************************
 * NAME
 * 
 * DESCRIPTION
 *	Copy DOS header information to structure.
 *
 * ARGUMENTS
 */
BOOL WINAPI 
GetDosHeader (
	       LPVOID lpFile,
	       PIMAGE_DOS_HEADER pHeader
)
{
  /*
   * DOS header represents first structure
   * of bytes in PE image file.
   */
  if ((WORD) IMAGE_DOS_SIGNATURE == *(WORD *) lpFile)
    {
      bcopy (
	      lpFile,
	      (LPVOID) pHeader,
	      sizeof (IMAGE_DOS_HEADER)
	);
      return TRUE;
    }
  return FALSE;
}




/* return file signature */
DWORD WINAPI 
ImageFileType (
		LPVOID lpFile)
{
  /* dos file signature comes first */
  if (*(USHORT *) lpFile == IMAGE_DOS_SIGNATURE)
    {
      /* determine location of PE File header from dos header */
      if (LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE ||
	  LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE)
	return (DWORD) LOWORD (*(DWORD *) NTSIGNATURE (lpFile));

      else if (*(DWORD *) NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE)
	return IMAGE_NT_SIGNATURE;

      else
	return IMAGE_DOS_SIGNATURE;
    }

  else
    /* unknown file type */
    return 0;
}




/* copy file header information to structure */
BOOL WINAPI 
GetPEFileHeader (
		  LPVOID lpFile,
		  PIMAGE_FILE_HEADER pHeader)
{
  /* file header follows dos header */
  if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
    bcopy (PEFHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_FILE_HEADER));
  else
    return FALSE;

  return TRUE;
}





/* copy optional header info to structure */
BOOL WINAPI 
GetPEOptionalHeader (
		      LPVOID lpFile,
		      PIMAGE_OPTIONAL_HEADER pHeader)
{
  /* optional header follows file header and dos header */
  if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
    bcopy (OPTHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_OPTIONAL_HEADER));
  else
    return FALSE;

  return TRUE;
}




/* function returns the entry point for an exe module lpFile must
   be a memory mapped file pointer to the beginning of the image file */
LPVOID WINAPI 
GetModuleEntryPoint (
		      LPVOID lpFile)
{
  PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);

  if (poh != NULL)
    return (LPVOID) (poh->AddressOfEntryPoint);
  else
    return NULL;
}




/* return the total number of sections in the module */
int WINAPI 
NumOfSections (
		LPVOID lpFile)
{
  /* number os sections is indicated in file header */
  return ((int) ((PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile))->NumberOfSections);
}




/* retrieve entry point */
LPVOID WINAPI 
GetImageBase (
	       LPVOID lpFile)
{
  PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);

  if (poh != NULL)
    return (LPVOID) (poh->ImageBase);
  else
    return NULL;
}



//
// This function is written by sang cho
//                                                 .. october 5, 1997
//
/* function returns the actual address of given RVA,      lpFile must
   be a memory mapped file pointer to the beginning of the image file */
LPVOID WINAPI 
GetActualAddress (
		   LPVOID lpFile,
		   DWORD dwRVA)
{
//    PIMAGE_OPTIONAL_HEADER   poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
  PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);
  int nSections = NumOfSections (lpFile);
  int i = 0;

  if ((void*)dwRVA == NULL)
    return NULL;
  if (dwRVA & 0x80000000)
    {
      //return (LPVOID)dwRVA;
      printf ("\n$$ what is going on $$");
      exit (0);
    }

  /* locate section containing image directory */
  while (i++ < nSections)
    {
      if (psh->VirtualAddress <= (DWORD) dwRVA &&
	  psh->VirtualAddress + psh->SizeOfRawData > (DWORD) dwRVA)
	break;
      psh++;
    }

  if (i > nSections)
    return NULL;

  /* return image import directory offset */
  return (LPVOID) (((int) lpFile + (int) dwRVA - psh->VirtualAddress) +
		   (int) psh->PointerToRawData);
}


//
// This function is modified by sang cho
//
//
/* return offset to specified IMAGE_DIRECTORY entry */
LPVOID WINAPI 
ImageDirectoryOffset (
		       LPVOID lpFile,
		       DWORD dwIMAGE_DIRECTORY)
{
  PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);
  PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);
  int nSections = NumOfSections (lpFile);
  int i = 0;
  LPVOID VAImageDir;

  /* must be 0 thru (NumberOfRvaAndSizes-1) */
  if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
    return NULL;

  /* locate specific image directory's relative virtual address */
  VAImageDir = (LPVOID) poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;

  if (VAImageDir == NULL)
    return NULL;
  /* locate section containing image directory */
  while (i++ < nSections)
    {
      if (psh->VirtualAddress <= (DWORD) VAImageDir &&
	  psh->VirtualAddress + psh->SizeOfRawData > (DWORD) VAImageDir)
	break;
      psh++;
    }

  if (i > nSections)
    return NULL;

  /* return image import directory offset */
  return (LPVOID) (((int) lpFile + (int) VAImageDir - psh->VirtualAddress) +
		   (int) psh->PointerToRawData);
}


/* function retrieve names of all the sections in the file */
int WINAPI 
GetSectionNames (
		  LPVOID lpFile,
		  char **pszSections)
{
  int nSections = NumOfSections (lpFile);
  int i, nCnt = 0;
  PIMAGE_SECTION_HEADER psh;
  char *ps;


  if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE ||
      (psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) == NULL)
    return 0;

  /* count the number of chars used in the section names */
  for (i = 0; i < nSections; i++)
    nCnt += strlen ( (const char*) psh[i].Name) + 1;


  /* allocate space for all section names from heap */
  ps = *pszSections = (char *) calloc (nCnt, 1);


  for (i = 0; i < nSections; i++)
    {
      strcpy (ps, (const char*)psh[i].Name);
      ps += strlen ((const char*)psh[i].Name) + 1;
    }

  return nCnt;
}




/* function gets the function header for a section identified by name */
BOOL WINAPI 
GetSectionHdrByName (
		      LPVOID lpFile,
		      IMAGE_SECTION_HEADER * sh,
		      char *szSection)
{
  PIMAGE_SECTION_HEADER psh;
  int nSections = NumOfSections (lpFile);
  int i;


  if ((psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) != NULL)
    {
      /* find the section by name */
      for (i = 0; i < nSections; i++)
	{
	  if (!strcmp ((const char*)psh->Name, szSection))
	    {
	      /* copy data to header */
	      bcopy ((LPVOID) psh, (LPVOID) sh, sizeof (IMAGE_SECTION_HEADER));
	      return TRUE;
	    }
	  else
	    psh++;
	}
    }
  return FALSE;
}



//
// This function is modified by sang cho
//
//
/* get import modules names separated by null terminators, return module count */
int WINAPI 
GetImportModuleNames (
		       LPVOID lpFile,
		       char **pszModules)
{
  PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  //
  // sometimes there may be no section for idata or edata
  // instead rdata or data section may contain these sections ..
  // or even module names or function names are in different section.
  // so that's why we need to get actual address of RVAs each time.
  //         ...................sang cho..................
  //
  // PIMAGE_SECTION_HEADER     psh = (PIMAGE_SECTION_HEADER)
  // ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  // BYTE                  *pData = (BYTE *)pid;
  //      DWORD            *pdw = (DWORD *)pid;
  int nCnt = 0, nSize = 0, i;
  char *pModule[1024];		/* hardcoded maximum number of modules?? */
  char *psz;

  if (pid == NULL)
    return 0;

  // pData = (BYTE *)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);

  /* extract all import modules */
  while (pid->dwRVAModuleName)
    {
      /* allocate temporary buffer for absolute string offsets */
      //pModule[nCnt] = (char *)(pData + pid->dwRVAModuleName);
      pModule[nCnt] = (char *) GetActualAddress (lpFile, pid->dwRVAModuleName);
      nSize += strlen (pModule[nCnt]) + 1;

      /* increment to the next import directory entry */
      pid++;
      nCnt++;
    }

  /* copy all strings to one chunk of memory */
  *pszModules = (char *) calloc (nSize, 1);
  psz = *pszModules;
  for (i = 0; i < nCnt; i++)
    {
      strcpy (psz, pModule[i]);
      psz += strlen (psz) + 1;
    }
  return nCnt;
}


//
// This function is rewritten by sang cho
//
//
/* get import module function names separated by null terminators, return function count */
int WINAPI 
GetImportFunctionNamesByIndex (
				 LPVOID lpFile,
				 int indexModule,
				 //char *pszModule,
				 char **pszFunctions)
{
  PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
  ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  //
  // sometimes there may be no section for idata or edata
  // instead rdata or data section may contain these sections ..
  // or even module names or function names are in different section.
  // so that's why we need to get actual address each time.
  //         ...................sang cho..................
  //
  //PIMAGE_SECTION_HEADER           psh = (PIMAGE_SECTION_HEADER)
  //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
  //DWORD                  dwBase;
  int nCnt = 0, nSize = 0;
  int nnid = 0;
  int mnlength, i;
  DWORD dwFunctionName;
  DWORD dwFunctionAddress;
  char name[128];
  char buff[256];		// enough for any string ??
  //int i;

  char *psz;
  DWORD *pdw;

  //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);

  /* find module's pid */
  i=0;
  while (pid->dwRVAModuleName &&
	 //strcmp (pszModule, (char *) GetActualAddress (lpFile, pid->dwRVAModuleName))
	 (i<indexModule)
	 )
    {
	i++;
        pid++;
    }

  /* exit if the module is not found */
  if (!pid->dwRVAModuleName)
    return 0;

  // I am doing this to get rid of .dll from module name
  char * pszModule=  (char *) GetActualAddress (lpFile, pid->dwRVAModuleName);
  strcpy (name, pszModule);
  mnlength = strlen (pszModule);
  for (i = 0; i < mnlength; i++)
    if (name[i] == '.')
      break;
  name[i] = 0;
  mnlength = i;

  /* count number of function names and length of strings */
  dwFunctionName = pid->dwRVAFunctionNameList;

  // IMAGE_IMPORT_BY_NAME OR IMAGE_THUNK_DATA
  // modified by Sang Cho
  while (dwFunctionName &&
	 *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName)))
    {
      if ((*pdw) & 0x80000000)
	nSize += mnlength + 10 + 1 + 6;
      else
	nSize += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1 + 6;
      dwFunctionName += 4;
      nCnt++;
    }

  /* allocate memory  for function names */
  *pszFunctions = (char *) calloc (nSize, 1);
  psz = *pszFunctions;

  //
  // I modified this part to store function address (4 bytes),
  //                               ord number (2 bytes),
  //                                                      and      name strings (which was there originally)
  // so that's why there are 6 more bytes...... +6,  or +4 and +2 etc.
  // these informations are used where they are needed.
  //                      ...........sang cho..................
  //
  /* copy function names to mempry pointer */
  dwFunctionName = pid->dwRVAFunctionNameList;
  dwFunctionAddress = pid->dwRVAFunctionAddressList;
  while (dwFunctionName &&
	 *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName)))
    {
      if ((*pdw) & 0x80000000)
	{
	  *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress));
	  psz += 4;
	  *(short *) psz = *(short *) pdw;
	  psz += 2;
	  sprintf (buff, "%s:NoName%04d", name, nnid++);
	  strcpy (psz, buff);
	  psz += strlen (buff) + 1;
	}
      else
	{
	  *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress));
	  psz += 4;
	  *(short *) psz = (*(short *) GetActualAddress (lpFile, *pdw));
	  psz += 2;
	  strcpy (psz, (char *) GetActualAddress (lpFile, *pdw + 2));
	  psz += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1;
	}
      dwFunctionName += 4;
      dwFunctionAddress += 4;
    }

  return nCnt;
}




//
// This function is written by sang cho
//                                                         October 6, 1997
//
/* get numerically expressed string length */
int WINAPI 
GetStringLength (
		  char *psz)
{
  if (!isdigit (*psz))
    return 0;
  if (isdigit (*(psz + 1)))
    return (*psz - '0') * 10 + *(psz + 1) - '0';
  else
    return *psz - '0';
}




//
// This function is written by sang cho
//                                                         October 12, 1997
//

/* translate parameter part of condensed name */
void WINAPI 
GetPreviousParamString (
			 char *xpin,	// read-only source
			  char *xpout)	// translated result
 {
  int n = 0;
  char *pin, *pout;

  pin = xpin;
  pout = xpout;

  pin--;
  if (*pin == ',')
    pin--;
  else
    {
      printf ("\n **error PreviousParamString1 char = %c", *pin);
      exit (0);
    }

  while (*pin)
    {
      if (*pin == '>')
	n++;
      else if (*pin == '<')
	n--;
      else if (*pin == ')')
	n++;

      if (n > 0)
	{
	  if (*pin == '(')
	    n--;
	}
      else if (strchr (",(", *pin))
	break;
      pin--;
    }

  //printf("\n ----- %s", pin);
  if (strchr (",(", *pin))
    {
      pin++;
    }				// printf("\n %s", pin); }

  else
    {
      printf ("\n **error PreviousParamString2");
      exit (0);
    }

  n = xpin - pin - 1;
  strncpy (pout, pin, n);
  *(pout + n) = 0;
}




//
// This function is written by sang cho
//                                                         October 10, 1997
//

/* translate parameter part of condensed name */
void WINAPI 
TranslateParameters (
		      char **ppin,	// read-only source
		       char **ppout,	// translated result
		       char **pps)	// parameter stack
 {
  int i, n;
  char c;
  char name[128];
  char *pin, *pout, *ps;

  //printf(" %c ", **in);
  pin = *ppin;
  pout = *ppout;
  ps = *pps;
  c = *pin;
  switch (c)
    {
      // types processing
    case 'b':
      strcpy (pout, "byte");
      pout += 4;
      pin++;
      break;
    case 'c':
      strcpy (pout, "char");
      pout += 4;
      pin++;
      break;
    case 'd':
      strcpy (pout, "double");
      pout += 6;
      pin++;
      break;
    case 'f':
      strcpy (pout, "float");
      pout += 5;
      pin++;
      break;
    case 'g':
      strcpy (pout, "long double");
      pout += 11;
      pin++;
      break;
    case 'i':
      strcpy (pout, "int");
      pout += 3;
      pin++;
      break;
    case 'l':
      strcpy (pout, "long");
      pout += 4;
      pin++;
      break;
    case 's':
      strcpy (pout, "short");
      pout += 5;
      pin++;
      break;
    case 'v':
      strcpy (pout, "void");
      pout += 4;
      pin++;
      break;
      // postfix processing
    case 'M':
    case 'p':
      if (*(pin + 1) == 'p')
	{
	  *ps++ = 'p';
	  pin += 2;
	}
      else
	{
	  *ps++ = '*';
	  pin++;
	}
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    case 'q':
      *pout++ = '(';
      pin++;
      *ps++ = 'q';
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    case 'r':
      if (*(pin + 1) == 'p')
	{
	  *ps++ = 'r';
	  pin += 2;
	}
      else
	{
	  *ps++ = '&';
	  pin++;
	}
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
      // repeat processing
    case 't':
      if (isdigit (*(pin + 1)))
	{
	  n = *(pin + 1) - '0';
	  pin++;
	  pin++;
	  GetPreviousParamString (pout, name);
	  strcpy (pout, name);
	  pout += strlen (name);
	  for (i = 1; i < n; i++)
	    {
	      *pout++ = ',';
	      strcpy (pout, name);
	      pout += strlen (name);
	    }
	}
      else
	pin++;
      break;
      // prefix processing
    case 'u':
      strcpy (pout, "u");
      pout += 1;
      pin++;
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    case 'x':
      strcpy (pout, "const ");
      pout += 6;
      pin++;
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    case 'z':
      strcpy (pout, "static ");
      pout += 7;
      pin++;
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    default:
      strcpy (pout, "!1!");
      pout += 3;
      *pout++ = *pin++;
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    }
  // need to process postfix finally
  c = *(ps - 1);
  if (strchr ("tqx", c))
    {
      if (*(pin) && !strchr ("@$%", *(pin)))
	*pout++ = ',';
      *ppin = pin;
      *ppout = pout;
      *pps = ps;
      return;
    }
  switch (c)
    {
    case 'r':
      strcpy (pout, "*&");
      pout += 2;
      ps--;
      break;
    case 'p':
      strcpy (pout, "**");
      pout += 2;
      ps--;
      break;
    case '&':
      strcpy (pout, "&");
      pout += 1;
      ps--;
      break;
    case '*':
      strcpy (pout, "*");
      pout += 1;
      ps--;
      break;
    default:
      strcpy (pout, "!2!");
      pout += 3;
      ps--;
      break;
    }
  if (*(pin) && !strchr ("@$%", *(pin)))
    *pout++ = ',';
  *ppin = pin;
  *ppout = pout;
  *pps = ps;
}


//
// This function is written by sang cho
//                                                         October 11, 1997
//

/* translate parameter part of condensed name */
BOOL WINAPI 
StringExpands (
		char **ppin,	// read-only source
		 char **ppout,	// translated result
		 char **pps,	// parameter stack
		 Str_P * pcstr)	// currently stored string
 {
//      int         n;
  //      char        c;
  char *pin, *pout, *ps;
  Str_P c_str;
  BOOL stringMode = TRUE;

  pin = *ppin;
  pout = *ppout;
  ps = *pps;
  c_str = *pcstr;

  if (strncmp (pin, "bctr", 4) == 0)
    {
      strncpy (pout, c_str.pos, c_str.length);
      pout += c_str.length;
      pin += 4;
    }
  else if (strncmp (pin, "bdtr", 4) == 0)
    {
      *pout++ = '~';
      strncpy (pout, c_str.pos, c_str.length);
      pout += c_str.length;
      pin += 4;
    }
  else if (*pin == 'o')
    {
      strcpy (pout, "const ");
      pout += 6;
      pin++;
      stringMode = FALSE;
    }
  else if (*pin == 'q')
    {
      *pout++ = '(';
      pin++;
      *ps++ = 'q';
      stringMode = FALSE;
    }
  else if (*pin == 't')
    {
      //if (*(ps-1) == 't') { *pout++ = ','; pin++; }       // this also got me...
      //else                                                                                          october 12  .. sang
      {
	*pout++ = '<';
	pin++;
	*ps++ = 't';
      }
      stringMode = FALSE;
    }
  else if (strncmp (pin, "xq", 2) == 0)
    {
      *pout++ = '(';
      pin += 2;
      *ps++ = 'x';
      *ps++ = 'q';
      stringMode = FALSE;
    }
  else if (strncmp (pin, "bcall", 5) == 0)
    {
      strcpy (pout, "operator ()");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "bsubs", 5) == 0)
    {
      strcpy (pout, "operator []");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "bnwa", 4) == 0)
    {
      strcpy (pout, "operator new[]");
      pout += 14;
      pin += 4;
    }
  else if (strncmp (pin, "bdla", 4) == 0)
    {
      strcpy (pout, "operator delete[]");
      pout += 17;
      pin += 4;
    }
  else if (strncmp (pin, "bnew", 4) == 0)
    {
      strcpy (pout, "operator new");
      pout += 12;
      pin += 4;
    }
  else if (strncmp (pin, "bdele", 5) == 0)
    {
      strcpy (pout, "operator delete");
      pout += 15;
      pin += 5;
    }
  else if (strncmp (pin, "blsh", 4) == 0)
    {
      strcpy (pout, "operator <<");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "brsh", 4) == 0)
    {
      strcpy (pout, "operator >>");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "binc", 4) == 0)
    {
      strcpy (pout, "operator ++");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "bdec", 4) == 0)
    {
      strcpy (pout, "operator --");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "badd", 4) == 0)
    {
      strcpy (pout, "operator +");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "brplu", 5) == 0)
    {
      strcpy (pout, "operator +=");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "bdiv", 4) == 0)
    {
      strcpy (pout, "operator /");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "brdiv", 5) == 0)
    {
      strcpy (pout, "operator /=");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "bmul", 4) == 0)
    {
      strcpy (pout, "operator *");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "brmul", 5) == 0)
    {
      strcpy (pout, "operator *=");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "basg", 4) == 0)
    {
      strcpy (pout, "operator =");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "beql", 4) == 0)
    {
      strcpy (pout, "operator ==");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "bneq", 4) == 0)
    {
      strcpy (pout, "operator !=");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "bor", 3) == 0)
    {
      strcpy (pout, "operator |");
      pout += 10;
      pin += 3;
    }
  else if (strncmp (pin, "bror", 4) == 0)
    {
      strcpy (pout, "operator |=");
      pout += 11;
      pin += 4;
    }
  else if (strncmp (pin, "bcmp", 4) == 0)
    {
      strcpy (pout, "operator ~");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "bnot", 4) == 0)
    {
      strcpy (pout, "operator !");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "band", 4) == 0)
    {
      strcpy (pout, "operator &");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "brand", 5) == 0)
    {
      strcpy (pout, "operator &=");
      pout += 11;
      pin += 5;
    }
  else if (strncmp (pin, "bxor", 4) == 0)
    {
      strcpy (pout, "operator ^");
      pout += 10;
      pin += 4;
    }
  else if (strncmp (pin, "brxor", 5) == 0)
    {
      strcpy (pout, "operator ^=");
      pout += 11;
      pin += 5;
    }
  else
    {
      strcpy (pout, "!$$$!");
      pout += 5;
    }
  *ppin = pin;
  *ppout = pout;
  *pps = ps;
  return stringMode;
}				// end of '$' processing



//----------------------------------------------------------------------
// structure to store string tokens
//----------------------------------------------------------------------
//typedef struct _Str_P {
//    char    flag;               // string_flag '@' or '%' or '#'
//    char    *pos;               // starting postion of string
//    int     length;     // length of string
//      BOOL    wasString;    // if it were stringMode or not
//} Str_P;
//----------------------------------------------------------------------
//
// I think I knocked it down finally. But who knows? 
//                            october 12, 1997 ... sang
//
// well I have to rewrite whole part of TranslateFunctionName..
// this time I am a little bit more experienced than 5 days ago.
// or am i??? anyway i use stacks instead of recurcive calls
// and i hope this will take care of every symptoms i have experienced..
//                                                        october 10, 1997 .... sang
// It took a lot of time for me to figure out what is all about....
// but still some prefixes like z (static) 
//     -- or some types like b (byte) ,g (long double) ,s (short) --
//         -- or postfix  like M ( * )
//     -- or $or ( & ) which is pretty wierd.         .. added.. october 12
//     -- also $t business is quite tricky too. (templates) 
//             there may be a lot of things undiscovered yet....
// I am not so sure my interpretation is correct or not
// If I am wrong please let me know.
//                             october 8, 1997 .... sang
//
//
// This function is written by sang cho
//                                                         October 5, 1997
//
/* translate condesed import function name */
LPVOID WINAPI 
TranslateFunctionName (
			char *psz)
{


  int i,  n;
  char c, cc;

  static char buff[512];	// result of translation

  int is = 0;
  char pStack[32];		// parameter processing stack

  Str_P sStack[32];		// String processing stack

  Str_P tok;			// String token

  Str_P c_str;			// current string 

  int iend = 0;
  char *endTab[8];		// end of string position check

  char *ps;
  char *pin, *pout;
  BOOL stringMode = TRUE;

  if (*psz != '@')
    return psz;
  pin = psz;
  pout = buff;
  ps = pStack;

  //................................................................
  // serious users may need to run the following code.
  // so I may need to include some flag options...
  // If you want to know about how translation is done,
  // you can just revive following line and you can see it.
  //                                                 october 6, 1997 ... sang cho
  //printf ("\n................................... %s", psz); // for debugging...

  //pa = pb = pout;
  pin++;
  tok.flag = 'A';
  tok.pos = pout;
  tok.length = 0;
  tok.wasString = stringMode;
  sStack[is++] = tok;		// initialize sStack with dummy marker

  while (*pin)
    {
      while (*pin)
	{
	  c = *pin;

	  //---------------------------------------------
	  // check for the end of number specified string
	  //---------------------------------------------

	  if (iend > 0)
	    {
	      for (i = 0; i < iend; i++)
		if (pin == endTab[i])
		  break;
	      if (i < iend)
		{
		  // move the end of endTab to ith position
		  endTab[i] = endTab[iend - 1];
		  iend--;

		  // get top of the string stack
		  tok = sStack[is - 1];

		  // I am expecting '#' token from stack
		  if (tok.flag != '#')

		    {
		      printf ("\n**some serious error1** %c is = %d char = %c",
			      tok.flag, is, *pin);
		      exit (0);
		    }

		  // pop '#' token  I am happy now.
		  else
		    {		//if (c)
		      //printf("\n pop # token ... current char = %c", c);
		      //else printf("\n pop percent token..next char = NULL");

		      is--;
		    }

		  stringMode = tok.wasString;

		  if (!stringMode)
		    {
		      // need to process postfix finally
		      cc = *(ps - 1);
		      if (strchr ("qtx", cc))
			{
			  if (!strchr ("@$%", c))
			    *pout++ = ',';
			}
		      else
			{
			  switch (cc)
			    {
			    case 'r':
			      strcpy (pout, "*&");
			      pout += 2;
			      ps--;
			      break;
			    case 'p':
			      strcpy (pout, "**");
			      pout += 2;
			      ps--;
			      break;
			    case '&':
			      strcpy (pout, "&");
			      pout += 1;
			      ps--;
			      break;
			    case '*':
			      strcpy (pout, "*");
			      pout += 1;
			      ps--;
			      break;
			    default:
			      strcpy (pout, "!3!");
			      pout += 3;
			      ps--;
			      break;
			    }
			  if (!strchr ("@$%", c))
			    *pout++ = ',';
			}
		    }
		  // string mode restored...
		  else;
		}
	      else;		// do nothing.. 

	    }

	  //------------------------------------------------
	  // special control symbol processing:
	  //------------------------------------------------

	  if (strchr ("@$%", c))
	    break;

	  //---------------------------------------------------------------
	  // string part processing : no '$' met yet 
	  //                       or inside of '%' block
	  //                       or inside of '#' block (numbered string)
	  //---------------------------------------------------------------

	  else if (stringMode)
	    *pout++ = *pin++;
	  //else if (is > 1)         *pout++ = *pin++;

	  //------------------------------------------------ 
	  // parameter part processing: '$' met
	  //------------------------------------------------

	  else			// parameter processing

	    {
	      if (!isdigit (c))
		TranslateParameters (&pin, &pout, &ps);
	      else		// number specified string processing

		{
		  n = GetStringLength (pin);
		  if (n < 10)
		    pin++;
		  else
		    pin += 2;

		  // push '#' token
		  //if (*pin)
		  //printf("\n push # token .. char = %c", *pin);
		  //else printf("\n push percent token..next char = NULL");
		  tok.flag = '#';
		  tok.pos = pout;
		  tok.length = 0;
		  tok.wasString = stringMode;
		  sStack[is++] = tok;

		  // mark end of input string
		  endTab[iend++] = pin + n;
		  stringMode = TRUE;
		}
	    }
	}			// end of inner while loop
      //
      // beginning of new string or end of string ( quotation mark )
      //

      if (c == '%')
	{
	  pin++;		// anyway we have to proceed...

	  tok = sStack[is - 1];	// get top of the sStack

	  if (tok.flag == '%')
	    {
	      // pop '%' token and set c_str 
	      //if (*pin)
	      //printf("\n pop percent token..next char = %c", *pin);
	      //else printf("\n pop percent token..next char = NULL");
	      is--;
	      c_str = tok;
	      c_str.length = pout - c_str.pos;
	      if (*(ps - 1) == 't')
		{
		  *pout++ = '>';
		  ps--;
		  stringMode = tok.wasString;
		}
	      else
		{
		  printf ("\n**some string error3** stack = %c", *(ps - 1));
		  exit (0);
		}
	    }
	  else if (tok.flag == 'A' || tok.flag == '#')
	    {
	      // push '%' token
	      //if (*pin)
	      //printf("\n push percent token..next char = %c", *pin);
	      //else printf("\n push percent token..next char = NULL");
	      tok.flag = '%';
	      tok.pos = pout;
	      tok.length = 0;
	      tok.wasString = stringMode;
	      sStack[is++] = tok;
	    }
	  else
	    {
	      printf ("\n**some string error5**");
	      exit (0);
	    }
	}
      //
      // sometimes we need string to use as constructor name or destructor name
      //
      else if (c == '@')	// get string from previous marker  upto here. 

	{
	  pin++;
	  tok = sStack[is - 1];
	  c_str.flag = 'S';
	  c_str.pos = tok.pos;
	  c_str.length = pout - tok.pos;
	  c_str.wasString = stringMode;
	  *pout++ = ':';
	  *pout++ = ':';
	}
      //
      // we need to take care of parameter control sequence
      //
      else if (c == '$')	// need to precess template or parameter part

	{
	  pin++;
	  if (stringMode)
	    stringMode = StringExpands (&pin, &pout, &ps, &c_str);
	  else
	    {			// template parameter mode I guess  "$t"

	      if (is > 1)
		{
		  if (*pin == 't')
		    pin++;
		  else
		    {
		      printf ("\nMYGOODNESS1 %c", *pin);
		      exit (0);
		    }
		  //ps--;
		  //if (*ps == 't') *pout++ = '>';
		  //else { printf("\nMYGOODNESS2"); exit(0);}
		  *pout++ = ',';	//pin++; ..this almost blowed me....

		}
	      // real parameter mode I guess
	      // unexpected case is found ... humm what can I do...
	      else
		{
		  // this is newly found twist.. it really hurts.
		  if (ps <= pStack)
		    {
		      if (*pin == 'q')
			{
			  *ps++ = 'q';
			  *pout++ = '(';
			  pin++;
			}
		      else
			{
			  printf ("\n** I GIVEUP ***");
			  exit (0);
			}
		      continue;
		    }
		  ps--;
		  while (*ps != 'q')
		    {
		      if (*ps == '*')
			*pout++ = '*';
		      else if (*ps == '&')
			*pout++ = '&';
		      else if (*ps == 'p')
			{
			  *pout++ = '*';
			  *pout++ = '*';
			}
		      else if (*ps == 'r')
			{
			  *pout++ = '*';
			  *pout++ = '&';
			}
		      else
			{
			  printf ("\n*** SOMETHING IS WRONG1*** char= %c", *pin);
			  exit (0);
			}
		      ps--;
		    }
		  *pout++ = ')';
		  ps--;
		  while (*ps != 'q')
		    {
		      if (*ps == '*')
			*pout++ = '*';
		      else if (*ps == '&')
			*pout++ = '&';
		      else if (*ps == 'p')
			{
			  *pout++ = '*';
			  *pout++ = '*';
			}
		      else if (*ps == 'r')
			{
			  *pout++ = '*';
			  *pout++ = '&';
			}
		      else
			{
			  printf ("\n*** SOMETHING IS WRONG2***");
			  exit (0);
			}
		      ps--;
		    }
		  ps++;
		  *pout++ = ',';
		}
	    }
	}			// end of '$' processing

    }				// end of outer while loop
  //
  // need to process remaining parameter stack
  //

  while (ps > pStack)
    {
      ps--;
      switch (*ps)
	{
	case 't':
	  *pout++ = '>';
	  break;
	case 'q':
	  *pout++ = ')';
	  break;
	case 'x':
	  strcpy (pout, " const");
	  pout += 6;
	  break;
	case 'r':
	  strcpy (pout, "*&");
	  pout += 2;
	  break;
	case 'p':
	  strcpy (pout, "**");
	  pout += 2;
	  break;
	case '&':
	  *pout++ = '&';
	  break;
	case '*':
	  *pout++ = '*';
	  break;
	default:
	  strcpy (pout, "!4!");
	  pout += 3;
	  *pout++ = *ps;
	}
    }
  *pout = 0;
  return buff;
}



//
// This function is written by sang cho
//
//
/* get exported function names separated by null terminators, return count of functions */
int WINAPI 
GetExportFunctionNames (
			 LPVOID lpFile,
			 char **pszFunctions)
{
  //PIMAGE_SECTION_HEADER      psh;
  PIMAGE_EXPORT_DIRECTORY ped;
  //DWORD                      dwBase;
  DWORD imageBase;		//===========================

  char *pfns[8192] =
  {NULL,};			// maximum number of functions
  //=============================  

  char buff[256];		// enough for any string ??

  char *psz;			//===============================

  DWORD *pdwAddress;
  DWORD *pdw1;
  DWORD *pdwNames;
  WORD *pwOrd;
  int i, nCnt = 0, ntmp = 0;
  int enid = 0, ordBase = 1;	// usally ordBase is 1....

  int enames = 0;

  /* get section header and pointer to data directory for .edata section */
  ped = (PIMAGE_EXPORT_DIRECTORY)
    ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT);

  if (ped == NULL)
    return 0;

  //
  // sometimes there may be no section for idata or edata
  // instead rdata or data section may contain these sections ..
  // or even module names or function names are in different section.
  // so that's why we need to get actual address each time.
  //         ...................sang cho..................
  //
  //psh = (PIMAGE_SECTION_HEADER)
  //ImageDirectorySection(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT);

  //if (psh == NULL) return 0;

  //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);


  /* determine the offset of the export function names */

  pdwAddress = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfFunctions);

  imageBase = (DWORD) GetImageBase (lpFile);

  ordBase = ped->Base;

  if (ped->NumberOfNames > 0)
    {
      pdwNames = (DWORD *)
	GetActualAddress (lpFile, (DWORD) ped->AddressOfNames);
      pwOrd = (WORD *)
	GetActualAddress (lpFile, (DWORD) ped->AddressOfNameOrdinals);
      pdw1 = pdwAddress;

      /* figure out how much memory to allocate for all strings */
      for (i = 0; i < (int) ped->NumberOfNames; i++)
	{
	  nCnt += strlen ((char *)
		    GetActualAddress (lpFile, *(DWORD *) pdwNames)) + 1 + 6;
	  pdwNames++;
	}
      // get the number of unnamed functions
      for (i = 0; i < (int) ped->NumberOfFunctions; i++)
	if (*pdw1++)
	  ntmp++;
      // add memory required to show unnamed functions.
      if (ntmp > (int) ped->NumberOfNames)
	nCnt += 18 * (ntmp - (int) ped->NumberOfNames);

      /* allocate memory  for function names */

      *pszFunctions = (char *) calloc (nCnt, 1);
      pdwNames = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNames);

      /* copy string pointer to buffer */

      for (i = 0; i < (int) ped->NumberOfNames; i++)
	{
	  pfns[(int) (*pwOrd) + ordBase] =
	    (char *) GetActualAddress (lpFile, *(DWORD *) pdwNames);
	  pdwNames++;
	  pwOrd++;
	}

      psz = *pszFunctions;
    }

  for (i = ordBase; i < (int) ped->NumberOfFunctions + ordBase; i++)
    {
      if (*pdwAddress > 0)
	{
	  *(DWORD *) psz = imageBase + *pdwAddress;
	  psz += 4;
	  *(WORD *) psz = (WORD) (i);
	  psz += 2;
	  if (pfns[i])
	    {
	      strcpy (psz, pfns[i]);
	      psz += strlen (psz) + 1;
	    }
	  else
	    {
	      sprintf (buff, "ExpFn%04d()", enid++);
	      strcpy (psz, buff);
	      psz += 12;
	    }
	  enames++;
	}
      pdwAddress++;
    }

  return enames;

}


/* function indicates whether debug  info has been stripped from file */
BOOL WINAPI 
IsDebugInfoStripped (
		      LPVOID lpFile)
{
  PIMAGE_FILE_HEADER pfh;

  pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile);

  return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
}




/* retrieve the module name from the debug misc. structure */
int WINAPI 
RetrieveModuleName (
		     LPVOID lpFile,
		     char **pszModule)
{

  PIMAGE_DEBUG_DIRECTORY pdd;
  PIMAGE_DEBUG_MISC pdm = NULL;
  int nCnt=0;

  if (!(pdd = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG)))
    return 0;

  while (pdd->SizeOfData)
    {
      if (pdd->Type == IMAGE_DEBUG_TYPE_MISC)
	{
	  pdm = (PIMAGE_DEBUG_MISC) ((DWORD) pdd->PointerToRawData + (DWORD) lpFile);
	  *pszModule = (char *) calloc ((nCnt = (strlen ((const char*)pdm->Data))) + 1, 1);
	  // may need some unicode business here...above
	  bcopy (pdm->Data, *pszModule, nCnt);

	  break;
	}

      pdd++;
    }

  if (pdm != NULL)
    return nCnt;
  else
    return 0;
}





/* determine if this is a valid debug file */
BOOL WINAPI 
IsDebugFile (
	      LPVOID lpFile)
{
  PIMAGE_SEPARATE_DEBUG_HEADER psdh;

  psdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile;

  return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE);
}




/* copy separate debug header structure from debug file */
BOOL WINAPI 
GetSeparateDebugHeader (
			 LPVOID lpFile,
			 PIMAGE_SEPARATE_DEBUG_HEADER psdh)
{
  PIMAGE_SEPARATE_DEBUG_HEADER pdh;

  pdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile;

  if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
    {
      bcopy ((LPVOID) pdh, (LPVOID) psdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER));
      return TRUE;
    }

  return FALSE;
}


///////////////////// Class declaration

using namespace std;

class dllSymbolData
{
	int expo;
	string  name;
	DWORD addr;
	DWORD hint;
	DWORD ord;
	DWORD data;

public:
	dllSymbolData();
	dllSymbolData(string name, DWORD addr,DWORD hint);
	dllSymbolData(string _name, DWORD _addr,DWORD _ord,DWORD _data);
	/*explicit*/ void symbolsDump(FILE*out);
};

class dllFile 
{
	// attention a la copie
	string filename;

public: // for now
	map< string, class dllSymbolData >  symbols;

public:
	dllFile();
	dllFile(string name);
    	void symbolsDump(FILE*out);
	string getFilename();
};

class winFile 
{
	string exeName;

public:  //transitoire
	map <string, class dllFile> impFile ;
	map< string, class dllSymbolData >  expSymbols;

public:
	winFile(string);
    	void symbolsDump(FILE*out);
};

typedef unsigned int uint;

///////////////////// Class implementation

dllSymbolData::dllSymbolData(string _name, DWORD _addr,DWORD _ord,DWORD _data)
{
	expo=1;
	name=_name;
	addr=_addr;
	ord=_ord;
	data=_data;
}

dllSymbolData::dllSymbolData(string _name, DWORD _addr,DWORD _hint)
{
	expo=0;
	name=_name;
	addr=_addr;
	hint=_hint;
}

dllSymbolData:: dllSymbolData()
{
	expo=0;
	name="";
	addr=0;
	hint=0;
}

void dllSymbolData::symbolsDump(FILE*out)
{
	if (expo)
	{
	fprintf (out, "Addr:%8.8x Ord: %3.3d (%4.4xh) Name: %s\n", 
		(uint)addr,
		(uint)ord,
		(uint)data,
		name.c_str()
		);
	}
	else
	{
	fprintf (out, "Addr:%8.8x hint(%4.4x) Name: %s\n", 
		(uint)addr,
		(uint)hint,
		name.c_str()
		);
	}
}

dllFile:: dllFile() 
{
	dllFile ("unnamed");
}

dllFile:: dllFile(string _name) :
	filename(_name),
	symbols ( map <string,class dllSymbolData>()  )
{

}

void dllFile::symbolsDump(FILE*out)
{
	fprintf (out, "  Import Module : :%s\n", filename.c_str());
	fprintf (out, "\n" );

	map <string , class dllSymbolData >::iterator it;
	for ( it=symbols.begin() ; it != symbols.end() ; it++ )
	{
		it->second .symbolsDump(out);
	}
	fprintf (out, "\n" );
}

string dllFile::getFilename()
{
	return filename;
}

winFile:: winFile(string name) :
	impFile ( map <string,class dllFile>()  ) ,
	expSymbols ( map <string,class dllSymbolData>()  )
{
	exeName = (name) ;
}

void winFile::symbolsDump(FILE*out)
{
//  printf ("\n\nDump of file: %s\n\n", argv[1]);
	fprintf (out, "Dump of file:%s\n", exeName.c_str());
	fprintf (out, "\n" );

	map <string , class dllFile >::iterator it;
	for ( it=impFile.begin() ; it != impFile.end() ; it++ )
	{
		it->second.symbolsDump(out);
	}


	fprintf (out, "  Exported functions  : %s\n", exeName.c_str());
	fprintf (out, "\n" );

	map <string , class dllSymbolData >::iterator is;
	for ( is=expSymbols.begin() ; is != expSymbols.end() ; is++ )
	{
		is->second .symbolsDump(out);
	}
	fprintf (out, "\n" );


}

void searchDependencies (
        class winFile & dll
)
{
}

///////////////////// Class use


#define  MAXSECTIONNUMBER 16
#define  MAXNAMESTRNUMBER 40
int 
load (
  	FILE *my_fp,
	class winFile & dll,
	char ** argv
)
{
  DWORD fileType;
  LPVOID lpFile;
  IMAGE_DOS_HEADER dosHdr;
  PIMAGE_FILE_HEADER pfh;
  PIMAGE_OPTIONAL_HEADER poh;
  PIMAGE_SECTION_HEADER psh;

  IMAGE_SECTION_HEADER shdr[MAXSECTIONNUMBER];

  int nSections;		// number of sections

  int nResources;		// number of resources


  int nImportedModules;		// number of imported modules

  int nFunctions;		// number of functions in the imported module

  int nExportedFunctions;	// number of exported funcions

  int imageBase;
  int entryPoint;

  int i, j,  n;
  int fsize;
  char *pnstr;
  char *pst;
  char *piNameBuff;		// import module name buffer

  char *pfNameBuff;		// import functions in the module name buffer

  char *peNameBuff;		// export function name buffer




  /*
   * Get input file's size.
   */
  /* argv [0], */
  fseek (my_fp, 0L, SEEK_END);
  fsize = ftell (my_fp);
  rewind (my_fp);
  /*
   * Buffer the file in memory.
   */
  lpFile = (void *) calloc (fsize, 1);
  if (lpFile == NULL)
    {
      printf (
	       "xx: can not allocate memory.\n"
	       //argv[0]
	);
      exit (0);
    }

  /*
   * --- Start of report ---
   */

  n = fread (lpFile, fsize, 1, my_fp);

  if (n == -1)
    {
      printf (
	       "%s: failed to read the file \"%s\".\n",
	       argv[0],
	       argv[1]
	);
      exit (0);
    }

  GetDosHeader (lpFile, &dosHdr);

  if ((WORD) IMAGE_DOS_SIGNATURE == dosHdr.e_magic)
    {
      if ((dosHdr.e_lfanew > 4096)
	  || (dosHdr.e_lfanew < 64)
	)
	{
	  printf (
		   "%s: This file is not in PE format; it looks like in DOS format.\n",
		   argv[0]
	    );
	  exit (0);
	}
    }
  else
    {
      printf (
	"%s: This doesn't look like an executable file (magic = 0x%04x).\n",
	       argv[0],
	       dosHdr.e_magic
	);
      exit (0);
    }

  fileType = ImageFileType (lpFile);

  if (fileType != IMAGE_NT_SIGNATURE)
    {
      printf (
	       "%s: This file is not in PE format (magic = 0x%08x).\n",
	       argv[0],
	       (uint)fileType
	);
      exit (0);
    }

  //=====================================
  // now we can really start processing
  //=====================================

  pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile);

  poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);

  psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);

  nSections = pfh->NumberOfSections;

  imageBase = poh->ImageBase;

  entryPoint = poh->AddressOfEntryPoint;

  if (psh == NULL)
    return 0;

  /* store section headers */

  for (i = 0;
       i < nSections;
       i++
    )
    {
      shdr[i] = *psh++;
    }
  /*
   * Get Code offset and size,
   * Data offset and size.
   */
  for (i = 0;
       i < nSections;
       i++
    )
    {
      if (poh->BaseOfCode == shdr[i].VirtualAddress)
	{
	  /*
	  printf (
		   "Code Offset = %08X, Code Size = %08X \n",
		   (uint)shdr[i].PointerToRawData,
		   (uint)shdr[i].SizeOfRawData
	    );
	    */
	}
      if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040)
	{
	  /*
	  printf (
		   "Data Offset = %08X, Data Size = %08X \n",
		   (uint)shdr[i].PointerToRawData,
		   (uint)shdr[i].SizeOfRawData
	    );
	    */
	  break;
	}
    }

  /*
  printf ("\n");

  printf (
	   "Number of Objects = %04d (dec), Imagebase = %08Xh \n",
	   nSections,
	   imageBase
    );
    */


  /*
   * Object name alignment.
   */
  for (i = 0;
       i < nSections;
       i++
    )
    {
      for (j = 0;
	   j < 7;
	   j++
	)
	{
	  if (shdr[i].Name[j] == 0)
	    {
	      shdr[i].Name[j] = 32;
	    }
	}
      shdr[i].Name[7] = 0;
    }
  /*
  for (i = 0; i < nSections; i++)
    printf ("\n   Object%02d: %8s RVA: %08X Offset: %08X Size: %08X Flags: %08X ",
      i + 1, shdr[i].Name, 
            (uint)shdr[i].VirtualAddress, 
	    (uint)shdr[i].PointerToRawData,
	    (uint)shdr[i].SizeOfRawData, 
	    (uint)shdr[i].Characteristics);
	    */

  /*
   * Get List of Resources.
   */
  nResources = 0;
  pst = pnstr;
  /*
  printf ("\n");
  printf ("\n+++++++++++++++++++ RESOURCE INFORMATION +++++++++++++++++++");
  printf ("\n");
  if (nResources == 0)
    printf ("\n        We donyt care of  Resources .\n");
  else
{
    printf ("\n        We donyt care of  Resources .\n");
}

  printf ("\n+++++++++++++++++++ IMPORTED FUNCTIONS +++++++++++++++++++");
  */

  nImportedModules = GetImportModuleNames (lpFile, &piNameBuff);
  if (nImportedModules == 0)
    {
      //printf ("\n        There are no imported Functions in This Application.\n");
    }
  else
    {
      pnstr = piNameBuff;
      //printf ("\nNumber of Imported Modules = %4d (decimal)\n", nImportedModules);
      for (i = 0; i < nImportedModules; i++)
	{
	  //printf ("\n   Import Module %03d: %s", i + 1, pnstr);


	  dllFile curdll = dllFile (string (pnstr) );

	  dllFile old = dll.impFile[string(pnstr)] ;

	  if ( string("")==(old.getFilename()) )
	  {
	  	dll.impFile[string(pnstr)]=curdll;
	  }



	  pnstr += strlen ((char *) (pnstr)) + 1;
	}

      //printf ("\n");
      //printf ("\n+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++++");
      pnstr = piNameBuff;
      for (i = 0; i < nImportedModules; i++)
	{
	  string thisdllname = string(pnstr);
	  //printf ("\n\n   Import Module %03d: %s \n", i + 1, pnstr);
	  nFunctions = GetImportFunctionNamesByIndex (lpFile, i, &pfNameBuff);
	  pnstr += strlen ((char *) (pnstr)) + 1;
	  pst = pfNameBuff;
	  int addr;
	  int hint;
	  for (j = 0; j < nFunctions; j++)
	    {
		      addr=(*(int *) pst); 
		      hint = (*(short *) (pst + 4));
		      char * sym;
		      sym= (char*)TranslateFunctionName (pst + 6);
	      /*
	      printf ("\nAddr:%08X hint(%04X) Name: %s",
	      	addr,hint,
	      //(pst+6));
		      sym);
		      */

	  dllSymbolData dsd= dllSymbolData ( string(sym), addr,hint);
	  dll.impFile[thisdllname].symbols[string(sym)] = dsd;

	      pst += strlen ((char *) (pst + 6)) + 1 + 6;
	    }
	  free ((void *) pfNameBuff);
	}
      free ((void *) piNameBuff);
    }

  //printf ("\n");
  //printf ("\n+++++++++++++++++++ EXPORTED FUNCTIONS +++++++++++++++++++");

  nExportedFunctions = GetExportFunctionNames (lpFile, &peNameBuff);
  //printf ("\nNumber of Exported Functions = %4d (decimal)\n", nExportedFunctions);

  if (nExportedFunctions > 0)
    {
      pst = peNameBuff;

      for (i = 0; i < nExportedFunctions; i++)
	{

	  string sym=string((char*)TranslateFunctionName (pst + 6));
	       int addr;
	       int ord;
	       int data;
	       addr = (*(int *) pst);
	       ord = (*(WORD *) (pst + 4));
	       data = (*(WORD *) (pst + 4));

	  /*
	  printf ("\nAddr:%08X Ord:%4d (%04Xh) Name: %s",
	  	addr,ord,data,
	       //(*(int *) pst), (*(WORD *) (pst + 4)), (*(WORD *) (pst + 4)),
	  //(pst+6));
		  sym.c_str() );
		  */

	  dllSymbolData dsd= dllSymbolData ( sym, addr,ord,data);
	  dll.expSymbols[sym] = dsd;


	  pst += strlen ((char *) (pst + 6)) + 6 + 1;
	}
      free ((void *) peNameBuff);
    }

  free ((void *) lpFile);

  return 0;
}




int 
main (
       int argc,
       char **argv
)
{
  FILE *my_fp;

  /*
   * Check user arguments.
   */
  if (2 == argc)
    {
      my_fp = fopen (argv[1], "rb");
      if (my_fp == NULL)
	{
	  printf (
		   "%s: can not open input file \"%s\".\n",
		   argv[0],
		   argv[1]
	    );
	  exit (0);
	}
    }
  else
    {
      printf (
	       "%s - PE/COFF file dumper\n"
	       "Copyright (c) 1993 Randy Kath (MSDN Technology Group)\n"
      "Copyright (c) 1997 Sang Cho (CS & Engineering - Chongju University)\n"
      "Copyright (c) 2000 Emanuele Aliberti (ReactOS Development Team)\n\n",
	       argv[0]
	);
      printf (
	       "usage: %s input_file_name\n",
	       argv[0]
	);
      exit (0);
    }
  class winFile dll(argv[1]);

    load (my_fp, dll, argv);
    dll.symbolsDump(stdout);
    searchDependencies (dll);

/* EOF */
}


More information about the Ros-kernel mailing list