PE image file dumper, by Sang Cho, adapted to ROS (wip).
authorEmanuele Aliberti <ea@iol.it>
Sat, 13 Jan 2001 18:19:23 +0000 (18:19 +0000)
committerEmanuele Aliberti <ea@iol.it>
Sat, 13 Jan 2001 18:19:23 +0000 (18:19 +0000)
svn path=/trunk/; revision=1505

rosapps/sysutils/pedump.c [new file with mode: 0644]

diff --git a/rosapps/sysutils/pedump.c b/rosapps/sysutils/pedump.c
new file mode 100644 (file)
index 0000000..81a8869
--- /dev/null
@@ -0,0 +1,4308 @@
+// $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@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 <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 GetImportFunctionNamesByModule (LPVOID, char *, 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 */
+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);
+
+/* 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 (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 (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, psh[i].Name);
+      ps += strlen (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 (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 
+GetImportFunctionNamesByModule (
+                                LPVOID lpFile,
+                                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 ??
+
+  char *psz;
+  DWORD *pdw;
+
+  //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
+
+  /* find module's pid */
+  while (pid->dwRVAModuleName &&
+        strcmp (pszModule, (char *) GetActualAddress (lpFile, pid->dwRVAModuleName)))
+    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
+  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, j, 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;
+
+}
+
+
+/* determine the total number of resources in the section */
+int WINAPI 
+GetNumberOfResources (
+                      LPVOID lpFile)
+{
+  PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
+  PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
+  int nCnt = 0, i;
+
+
+  /* get root directory of resource tree */
+  if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
+       (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
+    return 0;
+
+  /* set pointer to first resource type entry */
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  /* loop through all resource directory entry types */
+  for (i = 0; i < prdRoot->NumberOfIdEntries; i++)
+    {
+      /* locate directory or each resource type */
+      prdType = (PIMAGE_RESOURCE_DIRECTORY) ((int) prdRoot + (int) prde->OffsetToData);
+
+      /* mask off most significant bit of the data offset */
+      prdType = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType ^ 0x80000000);
+
+      /* increment count of name'd and ID'd resources in directory */
+      nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
+
+      /* increment to next entry */
+      prde++;
+    }
+
+  return nCnt;
+}
+
+
+
+//
+// This function is rewritten by sang cho
+//
+//
+/* name each type of resource in the section */
+int WINAPI 
+GetListOfResourceTypes (
+                        LPVOID lpFile,
+                        char **pszResTypes)
+{
+  PIMAGE_RESOURCE_DIRECTORY prdRoot;
+  PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
+  char *pMem;
+  char buff[32];
+  int nCnt, i;
+  DWORD prdeName;
+
+
+  /* get root directory of resource tree */
+  if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
+       (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
+    return 0;
+
+  /* allocate enuff space  to cover all types */
+  nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1);
+  *pszResTypes = (char *) calloc (nCnt, 1);
+  if ((pMem = *pszResTypes) == NULL)
+    return 0;
+
+  /* set pointer to first resource type entry */
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  /* loop through all resource directory entry types */
+  for (i = 0; i < prdRoot->NumberOfIdEntries; i++)
+    {
+      prdeName = prde->Name;
+
+      //if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME))
+      //    pMem += strlen (pMem) + 1;
+      //
+      // modified by ...................................Sang Cho..
+      // I can't user M/S provied funcitons here so I have to figure out
+      // how to do above functions. But I can settle down with the following
+      // code, which works pretty good for me.
+      //
+      if (prdeName == 1)
+       {
+         strcpy (pMem, "RT_CURSOR");
+         pMem += 10;
+       }
+      else if (prdeName == 2)
+       {
+         strcpy (pMem, "RT_BITMAP");
+         pMem += 10;
+       }
+      else if (prdeName == 3)
+       {
+         strcpy (pMem, "RT_ICON  ");
+         pMem += 10;
+       }
+      else if (prdeName == 4)
+       {
+         strcpy (pMem, "RT_MENU  ");
+         pMem += 10;
+       }
+      else if (prdeName == 5)
+       {
+         strcpy (pMem, "RT_DIALOG");
+         pMem += 10;
+       }
+      else if (prdeName == 6)
+       {
+         strcpy (pMem, "RT_STRING");
+         pMem += 10;
+       }
+      else if (prdeName == 7)
+       {
+         strcpy (pMem, "RT_FONTDIR");
+         pMem += 11;
+       }
+      else if (prdeName == 8)
+       {
+         strcpy (pMem, "RT_FONT  ");
+         pMem += 10;
+       }
+      else if (prdeName == 9)
+       {
+         strcpy (pMem, "RT_ACCELERATORS");
+         pMem += 16;
+       }
+      else if (prdeName == 10)
+       {
+         strcpy (pMem, "RT_RCDATA");
+         pMem += 10;
+       }
+      else if (prdeName == 11)
+       {
+         strcpy (pMem, "RT_MESSAGETABLE");
+         pMem += 16;
+       }
+      else if (prdeName == 12)
+       {
+         strcpy (pMem, "RT_GROUP_CURSOR");
+         pMem += 16;
+       }
+      else if (prdeName == 14)
+       {
+         strcpy (pMem, "RT_GROUP_ICON  ");
+         pMem += 16;
+       }
+      else if (prdeName == 16)
+       {
+         strcpy (pMem, "RT_VERSION");
+         pMem += 11;
+       }
+      else if (prdeName == 17)
+       {
+         strcpy (pMem, "RT_DLGINCLUDE  ");
+         pMem += 16;
+       }
+      else if (prdeName == 19)
+       {
+         strcpy (pMem, "RT_PLUGPLAY    ");
+         pMem += 16;
+       }
+      else if (prdeName == 20)
+       {
+         strcpy (pMem, "RT_VXD   ");
+         pMem += 10;
+       }
+      else if (prdeName == 21)
+       {
+         strcpy (pMem, "RT_ANICURSOR   ");
+         pMem += 16;
+       }
+      else if (prdeName == 22)
+       {
+         strcpy (pMem, "RT_ANIICON");
+         pMem += 11;
+       }
+      else if (prdeName == 0x2002)
+       {
+         strcpy (pMem, "RT_NEWBITMAP");
+         pMem += 13;
+       }
+      else if (prdeName == 0x2004)
+       {
+         strcpy (pMem, "RT_NEWMENU");
+         pMem += 11;
+       }
+      else if (prdeName == 0x2005)
+       {
+         strcpy (pMem, "RT_NEWDIALOG");
+         pMem += 13;
+       }
+      else if (prdeName == 0x7fff)
+       {
+         strcpy (pMem, "RT_ERROR ");
+         pMem += 10;
+       }
+      else
+       {
+         sprintf (buff, "RT_UNKNOWN:%08X", prdeName);
+         strcpy (pMem, buff);
+         pMem += 20;
+       }
+      prde++;
+    }
+
+  return prdRoot->NumberOfIdEntries;
+}
+
+
+
+//
+// This function is written by sang cho
+//                                                         October 12, 1997
+//
+/* copy menu information */
+void WINAPI 
+StrangeMenuFill (
+                 char **psz,   // results
+                  WORD ** pMenu,       // read-only
+                  int size)
+{
+  WORD *pwd;
+  WORD *ptr, *pmax;
+
+  pwd = *pMenu;
+  pmax = (WORD *) ((DWORD) pwd + size);
+  ptr = (WORD *) (*psz);
+
+  while (pwd < pmax)
+    {
+      *ptr++ = *pwd++;
+    }
+  *psz = (char *) ptr;
+  *pMenu = pwd;
+}
+
+
+
+//
+// This function is written by sang cho
+//                                                         October 1, 1997
+//
+/* obtain menu information */
+int WINAPI 
+MenuScan (
+          int *len,
+          WORD ** pMenu)
+{
+  int num = 0;
+  int ndetails;
+  WORD *pwd;
+  WORD flag, flag1;
+  WORD id, ispopup;
+
+
+  pwd = *pMenu;
+
+  flag = *pwd;                 // so difficult to correctly code this so let's try this
+
+  pwd++;
+  (*len) += 2;                 // flag store
+
+  if ((flag & 0x0010) == 0)
+    {
+      ispopup = flag;
+      id = *pwd;
+      pwd++;
+      (*len) += 2;             // id store
+
+    }
+  else
+    {
+      ispopup = flag;
+    }
+
+  while (*pwd)
+    {
+      (*len)++;
+      pwd++;
+    }
+  (*len)++;                    // name and null character
+
+  pwd++;                       // skip double null
+
+  if ((flag & 0x0010) == 0)    // normal node: done
+
+    {
+      *pMenu = pwd;
+      return (int) flag;
+    }
+  // popup node: need to go on...
+  while (1)
+    {
+      *pMenu = pwd;
+      flag1 = (WORD) MenuScan (len, pMenu);
+      pwd = *pMenu;
+      if (flag1 & 0x0080)
+       break;
+    }
+//  fill # of details to num above 
+  //(*len) += 2;
+  *pMenu = pwd;
+  return flag;
+}
+
+
+//
+// This function is written by sang cho
+//                                                         October 2, 1997
+//
+/* copy menu information */
+int WINAPI 
+MenuFill (
+          char **psz,
+          WORD ** pMenu)
+{
+  int num = 0;
+  int ndetails;
+  char *ptr, *pTemp;
+  WORD *pwd;
+  WORD flag, flag1;
+  WORD id, ispopup;
+
+  ptr = *psz;
+  pwd = *pMenu;
+  //flag = (*(PIMAGE_POPUP_MENU_ITEM *)pwd)->fItemFlags;
+  flag = *pwd;                 // so difficult to correctly code this so let's try this
+
+  pwd++;
+  if ((flag & 0x0010) == 0)
+    {
+      *(WORD *) ptr = flag;    // flag store
+
+      ptr += 2;
+      *(WORD *) ptr = id = *pwd;       // id store
+
+      ptr += 2;
+      pwd++;
+    }
+  else
+    {
+      *(WORD *) ptr = flag;    // flag store
+
+      ptr += 2;
+    }
+
+  while (*pwd)                 // name extract
+
+    {
+      *ptr = *(char *) pwd;
+      ptr++;
+      pwd++;
+    }                          //name and null character
+
+  *ptr = 0;
+  ptr++;
+  pwd++;                       // skip double null
+
+  if ((flag & 0x0010) == 0)    // normal node: done
+
+    {
+      *pMenu = pwd;
+      *psz = ptr;
+      return (int) flag;
+    }
+  //pTemp = ptr;
+  //ptr += 2;
+  // popup node: need to go on...
+  while (1)
+    {
+      //num++;
+      *pMenu = pwd;
+      *psz = ptr;
+      flag1 = (WORD) MenuFill (psz, pMenu);
+      pwd = *pMenu;
+      ptr = *psz;
+      if (flag1 & 0x0080)
+       break;
+    }
+//  fill # of details to num above 
+  //*(WORD *)pTemp = (WORD)num;
+  *pMenu = pwd;
+  *psz = ptr;
+  return flag;
+}
+
+
+//
+//==============================================================================
+// The following program is based on preorder-tree-traversal.
+// once you understand how to traverse..... 
+// the rest is pretty straight forward.
+// still we need to scan it first and fill it next time.
+// and finally we can print it.
+//
+// This function is written by sang cho
+//                                                         September 29, 1997
+//                                                         revised october 2, 1997
+//                             revised october 12, 1997
+// ..............................................................................
+// ------------------------------------------------------------------------------
+// I use same structure - which is used in P.E. programs - for my reporting.
+// So, my structure is as follows:
+//        # of menu name is stored else where ( in directory I suppose )
+//     supermenuname                    null terminated string, only ascii is considered.
+//         flag                 tells : node is a leaf or a internal node.
+//         popupname                    null terminated string
+//              
+//              flag                normal menu flag (leaf node)
+//                      id                                  normal menu id
+//              name                    normal menu name
+//         or                            or
+//              flag                        popup menu flag (internal node)
+//              popupname                   popup menu name 
+//             
+//                 flag                             it may folows
+//                         id                                   normal menu id
+//                 name                                 normal menu name
+//             or                                 or
+//                 flag                                 popup menu
+//                 popupname                    popup menu name
+//                                 .........
+//                                it goes on like this,
+//                                 but usually, it only goes a few steps,...
+// ------------------------------------------------------------------------------
+/* scan menu and copy menu */
+int WINAPI 
+GetContentsOfMenu (
+                   LPVOID lpFile,
+                   char **pszResTypes)
+{
+  PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage;
+  PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1;
+  PIMAGE_RESOURCE_DIR_STRING_U pMenuName;
+  PIMAGE_RESOURCE_DATA_ENTRY prData;
+  //PIMAGE_SECTION_HEADER              psh = (PIMAGE_SECTION_HEADER)
+  //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE);
+  PIMAGE_MENU_HEADER pMenuHeader;
+  PIMAGE_POPUP_MENU_ITEM pPopup;
+  PIMAGE_NORMAL_MENU_ITEM pNormal;
+  char buff[32];
+  int nCnt = 0, i, j;
+  int num = 0;
+  int size;
+  int sLength, nMenus;
+  WORD flag;
+  WORD *pwd;
+  DWORD prdeName;
+  //DWORD                   dwBase;    obsolete
+  char *pMem, *pTemp;
+  BOOL isStrange = FALSE;
+
+
+  /* get root directory of resource tree */
+  if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
+       (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
+    return 0;
+
+  /* set pointer to first resource type entry */
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  for (i = 0; i < prdType->NumberOfIdEntries; i++)
+    {
+      if (prde->Name == RT_MENU)
+       break;
+      prde++;
+    }
+  if (prde->Name != RT_MENU)
+    return 0;
+
+  prdName = (PIMAGE_RESOURCE_DIRECTORY)
+    ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+  if (prdName == NULL)
+    return 0;
+
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  // sometimes previous code tells you lots of things hidden underneath
+  // I wish I could save all the revisions I made ... but again .... sigh.
+  //                                  october 12, 1997    sang
+  //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
+
+  nMenus = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
+  sLength = 0;
+
+  for (i = 0; i < prdName->NumberOfNamedEntries; i++)
+    {
+      pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U)
+       ((DWORD) prdType + (prde->Name ^ 0x80000000));
+      sLength += pMenuName->Length + 1;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      pMenuHeader = (PIMAGE_MENU_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+
+      //
+      // normally wVersion and cbHeaderSize should be zero
+      // but if it is not then nothing is known to us...
+      // so let's do our best ... namely guessing .... and trying ....
+      //                      ... and suffering   ... 
+      // it gave me many sleepless (not exactly but I like to say this) nights.
+      //
+
+      // strange case
+      if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
+       {
+         //isStrange = TRUE;
+         pwd = (WORD *) ((DWORD) pMenuHeader + 16);
+         size = prData->Size;
+         // expect to return the length needed to report.
+         // sixteen more bytes to do something
+         sLength += 16 + size;
+         //StrangeMenuScan (&sLength, &pwd, size);   
+       }
+      // normal case
+      else
+       {
+         pPopup = (PIMAGE_POPUP_MENU_ITEM)
+           ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
+         while (1)
+           {
+             flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup));
+             if (flag & 0x0080)
+               break;
+           }
+       }
+      prde++;
+    }
+  for (i = 0; i < prdName->NumberOfIdEntries; i++)
+    {
+      sLength += 12;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      pMenuHeader = (PIMAGE_MENU_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+      // strange case
+      if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
+       {
+         pwd = (WORD *) ((DWORD) pMenuHeader + 16);
+         size = prData->Size;
+         // expect to return the length needed to report.
+         // sixteen more bytes to do something
+         sLength += 16 + size;
+         //StrangeMenuScan (&sLength, &pwd, size);
+       }
+      // normal case
+      else
+       {
+         pPopup = (PIMAGE_POPUP_MENU_ITEM)
+           ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
+         while (1)
+           {
+             flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup));
+             if (flag & 0x0080)
+               break;
+           }
+       }
+      prde++;
+    }
+  //
+  // allocate memory for menu names
+  //
+  *pszResTypes = (char *) calloc (sLength, 1);
+
+  pMem = *pszResTypes;
+  //
+  // and start all over again
+  //
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  for (i = 0; i < prdName->NumberOfNamedEntries; i++)
+    {
+      pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U)
+       ((DWORD) prdType + (prde->Name ^ 0x80000000));
+
+
+      for (j = 0; j < pMenuName->Length; j++)
+       *pMem++ = (char) (pMenuName->NameString[j]);
+      *pMem = 0;
+      pMem++;
+
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      pMenuHeader = (PIMAGE_MENU_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+      // strange case
+      if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
+       {
+         pwd = (WORD *) ((DWORD) pMenuHeader);
+         size = prData->Size;
+         strcpy (pMem, ":::::::::::");
+         pMem += 12;
+         *(int *) pMem = size;
+         pMem += 4;
+         StrangeMenuFill (&pMem, &pwd, size);
+       }
+      // normal case
+      else
+       {
+         pPopup = (PIMAGE_POPUP_MENU_ITEM)
+           ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
+         while (1)
+           {
+             flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup));
+             if (flag & 0x0080)
+               break;
+           }
+       }
+      prde++;
+    }
+  for (i = 0; i < prdName->NumberOfIdEntries; i++)
+    {
+
+      sprintf (buff, "MenuId_%04X", (prde->Name));
+      strcpy (pMem, buff);
+      pMem += strlen (buff) + 1;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      pMenuHeader = (PIMAGE_MENU_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+      // strange case
+      if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
+       {
+         pwd = (WORD *) ((DWORD) pMenuHeader);
+         size = prData->Size;
+         strcpy (pMem, ":::::::::::");
+         pMem += 12;
+         *(int *) pMem = size;
+         pMem += 4;
+         StrangeMenuFill (&pMem, &pwd, size);
+       }
+      // normal case
+      else
+       {
+         pPopup = (PIMAGE_POPUP_MENU_ITEM)
+           ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
+         while (1)
+           {
+             flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup));
+             if (flag & 0x0080)
+               break;
+           }
+       }
+      prde++;
+    }
+
+  return nMenus;
+}
+
+
+//
+// This function is written by sang cho
+//                                                         October 12, 1997
+//
+/* print contents of menu */
+int WINAPI 
+PrintStrangeMenu (
+                  char **psz)
+{
+
+  int i, j, k, l;
+  int num;
+  WORD flag1, flag2;
+  char buff[128];
+  char *ptr, *pmax;
+
+  //return dumpMenu (psz, size);
+
+  ptr = *psz;
+
+  if (strncmp (ptr, ":::::::::::", 11) != 0)
+    {
+      printf ("\n#### I don't know why!!!");
+      dumpMenu (psz, 1024);
+      exit (0);
+    }
+
+  ptr += 12;
+  num = *(int *) ptr;
+  ptr += 4;
+  pmax = ptr + num;
+
+  *psz = ptr;
+  return dumpMenu (psz, num);
+
+  // I will write some code later...
+
+}
+
+
+
+
+//
+// This function is written by sang cho
+//                                                         October 2, 1997
+//
+/* print contents of menu */
+int WINAPI 
+PrintMenu (
+           int indent,
+           char **psz)
+{
+
+  int /*i, */ j, k, l;
+  WORD id /*, num */ ;
+  WORD flag;
+  char buff[128];
+  char *ptr;
+
+
+  ptr = *psz;
+  //num = *(WORD *)ptr;
+  //ptr += 2;
+  while (1)
+    {
+      flag = *(WORD *) ptr;
+      if (flag & 0x0010)       // flag == popup
+
+       {
+         printf ("\n\n");
+         for (j = 0; j < indent; j++)
+           printf (" ");
+         ptr += 2;
+         printf ("%s  {Popup}\n", ptr);
+         ptr += strlen (ptr) + 1;
+         *psz = ptr;
+         PrintMenu (indent + 5, psz);
+         ptr = *psz;
+       }
+      else                     // ispopup == 0 
+
+       {
+         printf ("\n");
+         for (j = 0; j < indent; j++)
+           printf (" ");
+         ptr += 2;
+         id = *(WORD *) ptr;
+         ptr += 2;
+         strcpy (buff, ptr);
+         l = strlen (ptr);
+         ptr += l + 1;
+         if (strchr (buff, 0x09) != NULL)
+           {
+             for (k = 0; k < l; k++)
+               if (buff[k] == 0x09)
+                 break;
+             for (j = 0; j < l - k; j++)
+               buff[31 - j] = buff[l - j];
+             for (j = k; j < 32 + k - l; j++)
+               buff[j] = 32;
+           }
+         if (strchr (buff, 0x08) != NULL)
+           {
+             for (k = 0; k < l; k++)
+               if (buff[k] == 0x08)
+                 break;
+             for (j = 0; j < l - k; j++)
+               buff[31 - j] = buff[l - j];
+             for (j = k; j < 32 + k - l; j++)
+               buff[j] = 32;
+           }
+         printf ("%s", buff);
+         l = strlen (buff);
+         for (j = l; j < 32; j++)
+           printf (" ");
+         printf ("[ID=%04Xh]", id);
+         *psz = ptr;
+       }
+      if (flag & 0x0080)
+       break;
+    }
+  return 0;
+}
+
+
+//
+// This function is written by sang cho
+//                                                         October 2, 1997
+//
+/* the format of menu is not known so I'll do my best */
+int WINAPI 
+dumpMenu (
+          char **psz,
+          int size)
+{
+
+  int i, j, k, n, l, c;
+  char buff[32];
+  char *ptr, *pmax;
+
+  ptr = *psz;
+  pmax = ptr + size;
+  for (i = 0; i < (size / 16) + 1; i++)
+    {
+      n = 0;
+      for (j = 0; j < 16; j++)
+       {
+         c = (int) (*ptr);
+         if (c < 0)
+           c += 256;
+         buff[j] = c;
+         printf ("%02X", c);
+         ptr++;
+         if (ptr >= pmax)
+           break;
+         n++;
+         if (n % 4 == 0)
+           printf (" ");
+       }
+      n++;
+      if (n % 4 == 0)
+       printf (" ");
+      l = j;
+      j++;
+      for (; j < 16; j++)
+       {
+         n++;
+         if (n % 4 == 0)
+           printf ("   ");
+         else
+           printf ("  ");
+       }
+      printf ("   ");
+      for (k = 0; k < l; k++)
+       if (isprint (c = buff[k]))
+         printf ("%c", c);
+       else
+         printf (".");
+      printf ("\n");
+      if (ptr >= pmax)
+       break;
+    }
+
+  *psz = ptr;
+  return 0;
+}
+
+
+
+
+//
+// This function is written by sang cho
+//                                                         October 13, 1997
+//
+/* scan dialog box and copy dialog box */
+int WINAPI 
+GetContentsOfDialog (
+                     LPVOID lpFile,
+                     char **pszResTypes)
+{
+  PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage;
+  PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1;
+  PIMAGE_RESOURCE_DIR_STRING_U pDialogName;
+  PIMAGE_RESOURCE_DATA_ENTRY prData;
+  PIMAGE_DIALOG_HEADER pDialogHeader;
+  PIMAGE_CONTROL_DATA pControlData;
+  char buff[32];
+  int nCnt = 0, i, j;
+  int num = 0;
+  int size;
+  int sLength, nDialogs;
+  WORD flag;
+  WORD *pwd;
+  DWORD prdeName;
+  char *pMem, *pTemp;
+  BOOL isStrange = FALSE;
+
+
+  /* get root directory of resource tree */
+  if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
+       (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
+    return 0;
+
+  /* set pointer to first resource type entry */
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  for (i = 0; i < prdType->NumberOfIdEntries; i++)
+    {
+      if (prde->Name == RT_DIALOG)
+       break;
+      prde++;
+    }
+  if (prde->Name != RT_DIALOG)
+    return 0;
+
+  prdName = (PIMAGE_RESOURCE_DIRECTORY)
+    ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+  if (prdName == NULL)
+    return 0;
+
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+
+  nDialogs = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
+  sLength = 0;
+
+  for (i = 0; i < prdName->NumberOfNamedEntries; i++)
+    {
+      pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U)
+       ((DWORD) prdType + (prde->Name ^ 0x80000000));
+      sLength += pDialogName->Length + 1;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      size = prData->Size;
+      sLength += 4 + size;
+      prde++;
+    }
+  for (i = 0; i < prdName->NumberOfIdEntries; i++)
+    {
+      sLength += 14;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      size = prData->Size;
+      sLength += 4 + size;
+      prde++;
+    }
+  //
+  // allocate memory for menu names
+  //
+  *pszResTypes = (char *) calloc (sLength, 1);
+
+  pMem = *pszResTypes;
+  //
+  // and start all over again
+  //
+  prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+    ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+  for (i = 0; i < prdName->NumberOfNamedEntries; i++)
+    {
+      pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U)
+       ((DWORD) prdType + (prde->Name ^ 0x80000000));
+
+
+      for (j = 0; j < pDialogName->Length; j++)
+       *pMem++ = (char) (pDialogName->NameString[j]);
+      *pMem = 0;
+      pMem++;
+
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       continue;
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       continue;
+
+      pDialogHeader = (PIMAGE_DIALOG_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+
+
+
+      pwd = (WORD *) ((DWORD) pDialogHeader);
+      size = prData->Size;
+      *(int *) pMem = size;
+      pMem += 4;
+      StrangeMenuFill (&pMem, &pwd, size);
+
+      prde++;
+    }
+  for (i = 0; i < prdName->NumberOfIdEntries; i++)
+    {
+
+      sprintf (buff, "DialogId_%04X", (prde->Name));
+      strcpy (pMem, buff);
+      pMem += strlen (buff) + 1;
+
+      prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
+       ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
+      if (prdLanguage == NULL)
+       {
+         printf ("\nprdLanguage = NULL");
+         exit (0);
+       }
+
+      prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
+       ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
+
+      prData = (PIMAGE_RESOURCE_DATA_ENTRY)
+       ((DWORD) prdType + prde1->OffsetToData);
+      if (prData == NULL)
+       {
+         printf ("\nprData = NULL");
+         exit (0);
+       }
+
+      pDialogHeader = (PIMAGE_DIALOG_HEADER)
+       GetActualAddress (lpFile, prData->OffsetToData);
+
+
+      pwd = (WORD *) ((DWORD) pDialogHeader);
+      size = prData->Size;
+      *(int *) pMem = size;
+      pMem += 4;
+      StrangeMenuFill (&pMem, &pwd, size);
+
+      prde++;
+    }
+
+  return nDialogs;
+}
+
+
+//
+// This function is written by sang cho
+//                                                         October 14, 1997
+//
+/* print contents of dialog */
+int WINAPI 
+PrintNameOrOrdinal (
+                    char **psz)
+{
+  char *ptr;
+
+  ptr = *psz;
+  if (*(WORD *) ptr == 0xFFFF)
+    {
+      ptr += 2;
+      printf ("%04X", *(WORD *) ptr);
+      ptr += 2;
+    }
+  else
+    {
+      printf ("%c", '"');
+      while (*(WORD *) ptr)
+       {
+         printf ("%c", *ptr);
+         ptr += 2;
+       }
+      ptr += 2;
+      printf ("%c", '"');
+    }
+  *psz = ptr;
+}
+
+
+//
+// This function is written by sang cho
+//                                                         October 14, 1997
+//
+/* print contents of dialog */
+int WINAPI 
+PrintDialog (
+             char **psz)
+{
+  int i, j, k, l, n, c;
+  int num, size;
+  DWORD flag;
+  WORD class;
+  char buff[32];
+  char *ptr, *pmax;
+  BOOL isStrange = FALSE;
+
+  ptr = *psz;
+  size = *(int *) ptr;
+  ptr += 4;
+  pmax = ptr + size;
+
+  // IStype of Dialog Header
+  flag = *(DWORD *) ptr;
+  //
+  // check if flag is right or not
+  // it has been observed that some dialog information is strange
+  // and extra work is needed to fix that ... so let's try something
+  //
+
+  if ((flag & 0xFFFF0000) == 0xFFFF0000)
+    {
+      flag = *(DWORD *) (ptr + 12);
+      num = *(short *) (ptr + 16);
+      isStrange = TRUE;
+      ptr += 26;
+    }
+  else
+    {
+      num = *(short *) (ptr + 8);
+      ptr += 18;
+    }
+  printf (", # of Controls=%03d, Caption:%c", num, '"');
+
+  // Menu name
+  if (*(WORD *) ptr == 0xFFFF)
+    ptr += 4;                  // ordinal
+
+  else
+    {
+      while (*(WORD *) ptr)
+       ptr += 2;
+      ptr += 2;
+    }                          // name
+
+  // Class name
+  if (*(WORD *) ptr == 0xFFFF)
+    ptr += 4;                  // ordinal
+
+  else
+    {
+      while (*(WORD *) ptr)
+       ptr += 2;
+      ptr += 2;
+    }                          // name
+
+  // Caption
+  while (*(WORD *) ptr)
+    {
+      printf ("%c", *ptr);
+      ptr += 2;
+    }
+  ptr += 2;
+  printf ("%c", '"');
+
+  // FONT present
+  if (flag & 0x00000040)
+    {
+      if (isStrange)
+       ptr += 6;
+      else
+       ptr += 2;               // FONT size
+
+      while (*(WORD *) ptr)
+       ptr += 2;               // WCHARs
+
+      ptr += 2;                        // double null  
+
+    }
+
+  // strange case adjust
+  if (isStrange)
+    ptr += 8;
+
+  // DWORD padding
+  if ((ptr - *psz) % 4)
+    ptr += 4 - ((ptr - *psz) % 4);
+
+  // start reporting .. finally
+  for (i = 0; i < num; i++)
+    {
+      flag = *(DWORD *) ptr;
+      if (isStrange)
+       ptr += 14;
+      else
+       ptr += 16;
+      printf ("\n     Control::%03d - ID:", i + 1);
+
+      // Control ID
+      printf ("%04X, Class:", *(WORD *) ptr);
+      ptr += 2;
+
+      // Control Class
+      if (*(WORD *) ptr == 0xFFFF)
+       {
+         ptr += 2;
+         class = *(WORD *) ptr;
+         ptr += 2;
+         switch (class)
+           {
+           case 0x80:
+             printf ("BUTTON   ");
+             break;
+           case 0x81:
+             printf ("EDIT     ");
+             break;
+           case 0x82:
+             printf ("STATIC   ");
+             break;
+           case 0x83:
+             printf ("LISTBOX  ");
+             break;
+           case 0x84:
+             printf ("SCROLLBAR");
+             break;
+           case 0x85:
+             printf ("COMBOBOX ");
+             break;
+           default:
+             printf ("%04X     ", class);
+             break;
+           }
+       }
+      else
+       PrintNameOrOrdinal (&ptr);
+
+      printf (" Text:");
+
+      // Text
+      PrintNameOrOrdinal (&ptr);
+
+      // nExtraStuff
+      ptr += 2;
+
+      // strange case adjust
+      if (isStrange)
+       ptr += 8;
+
+      // DWORD padding
+      if ((ptr - *psz) % 4)
+       ptr += 4 - ((ptr - *psz) % 4);
+    }
+
+  /*
+     ptr = *psz;
+     printf("\n");
+
+     for (i=0; i<(size/16)+1; i++)
+     {
+     n = 0;
+     for (j=0; j<16; j++)
+     {
+     c = (int)(*ptr);
+     if (c<0) c+=256;
+     buff[j] = c;
+     printf ("%02X",c);
+     ptr++; 
+     if (ptr >= pmax) break;
+     n++;
+     if (n%4 == 0) printf (" "); 
+     }
+     n++; if (n%4 == 0) printf (" ");
+     l = j;
+     j++;
+     for (; j<16; j++) 
+     { n++; if (n%4 == 0) printf ("   "); else printf ("  "); }
+     printf ("   ");
+     for (k=0; k<l; k++)
+     if (isprint(c=buff[k])) printf("%c", c); else printf(".");
+     printf ("\n");
+     if (ptr >= pmax) break;
+     }
+   */
+
+  *psz = pmax;
+
+}
+
+
+
+
+
+
+/* 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;
+
+  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 (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;
+}
+
+//
+// I tried to immitate the output of w32dasm disassembler.
+// which is a pretty good program.
+// but I am disappointed with this program and I myself 
+// am writting a disassembler.
+// This PEdump program is a byproduct of that project.
+// so enjoy this program and I hope we will have a little more
+// knowledge on windows programming world.
+//                                                        .... sang cho
+
+#define  MAXSECTIONNUMBER 16
+#define  MAXNAMESTRNUMBER 40
+int 
+main (
+       int argc,
+       char **argv
+)
+{
+  DWORD fileType;
+  LPVOID lpFile;
+  FILE *my_fp;
+  IMAGE_DOS_HEADER dosHdr;
+  PIMAGE_FILE_HEADER pfh;
+  PIMAGE_OPTIONAL_HEADER poh;
+  PIMAGE_SECTION_HEADER psh;
+  IMAGE_SECTION_HEADER idsh;
+  IMAGE_SECTION_HEADER shdr[MAXSECTIONNUMBER];
+  PIMAGE_IMPORT_MODULE_DIRECTORY pid;
+
+  int nSections;               // number of sections
+
+  int nResources;              // number of resources
+
+  int nMenus;                  // number of menus
+
+  int nDialogs;                        // number of dialogs
+
+  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, k, n;
+  int mnsize;
+  int nCnt;
+  int nSize;
+  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
+
+  char *pmNameBuff;            // menu name buffer
+
+  char *pdNameBuff;            // dialog name buffer
+
+  /*
+   * 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);
+    }
+  /*
+   * 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 (
+              "%s: can not allocate memory.\n",
+              argv[0]
+       );
+      exit (0);
+    }
+  /*
+   * --- Start of report ---
+   */
+  printf ("\n\nDump of file: %s\n\n", argv[1]);
+
+  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],
+              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",
+                  shdr[i].PointerToRawData,
+                  shdr[i].SizeOfRawData
+           );
+       }
+      if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040)
+       {
+         printf (
+                  "Data Offset = %08X, Data Size = %08X \n",
+                  shdr[i].PointerToRawData,
+                  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, shdr[i].VirtualAddress, shdr[i].PointerToRawData,
+           shdr[i].SizeOfRawData, shdr[i].Characteristics);
+  /*
+   * Get List of Resources.
+   */
+  nResources = GetListOfResourceTypes (lpFile, &pnstr);
+  pst = pnstr;
+  printf ("\n");
+  printf ("\n+++++++++++++++++++ RESOURCE INFORMATION +++++++++++++++++++");
+  printf ("\n");
+  if (nResources == 0)
+    printf ("\n        There are no Resources in This Application.\n");
+  else
+    {
+      printf ("\nNumber of Resource Types = %4d (decimal)\n", nResources);
+      for (i = 0; i < nResources; i++)
+       {
+         printf ("\n   Resource Type %03d: %s", i + 1, pst);
+         pst += strlen ((char *) (pst)) + 1;
+       }
+      free ((void *) pnstr);
+
+      printf ("\n");
+      printf ("\n+++++++++++++++++++ MENU INFORMATION +++++++++++++++++++");
+      printf ("\n");
+
+      nMenus = GetContentsOfMenu (lpFile, &pmNameBuff);
+
+      if (nMenus == 0)
+       {
+         printf ("\n        There are no Menus in This Application.\n");
+       }
+      else
+       {
+         pst = pmNameBuff;
+         printf ("\nNumber of Menus = %4d (decimal)", nMenus);
+
+         //dumpMenu(&pst, 8096); 
+         for (i = 0; i < nMenus; i++)
+           {
+             // menu ID print
+             printf ("\n\n%s", pst);
+             pst += strlen (pst) + 1;
+             printf ("\n-------------");
+             if (strncmp (pst, ":::::::::::", 11) == 0)
+               {
+                 printf ("\n");
+                 PrintStrangeMenu (&pst);
+               }
+             else
+               {
+                 PrintMenu (6, &pst);
+               }
+             //else PrintStrangeMenu(&pst);
+           }
+         free ((void *) pmNameBuff);
+         printf ("\n");
+       }
+
+      printf ("\n");
+      printf ("\n+++++++++++++++++ DIALOG INFORMATION +++++++++++++++++++");
+      printf ("\n");
+
+      nDialogs = GetContentsOfDialog (lpFile, &pdNameBuff);
+
+      if (nDialogs == 0)
+       {
+         printf ("\n        There are no Dialogs in This Application.\n");
+       }
+      else
+       {
+         pst = pdNameBuff;
+         printf ("\nNumber of Dialogs = %4d (decimal)", nDialogs);
+
+         printf ("\n");
+
+         for (i = 0; i < nDialogs; i++)
+           {
+             // Dialog ID print
+             printf ("\nName: %s", pst);
+             pst += strlen (pst) + 1;
+             PrintDialog (&pst);
+           }
+         free ((void *) pdNameBuff);
+         printf ("\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);
+         pnstr += strlen ((char *) (pnstr)) + 1;
+       }
+
+      printf ("\n");
+      printf ("\n+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++++");
+      pnstr = piNameBuff;
+      for (i = 0; i < nImportedModules; i++)
+       {
+         printf ("\n\n   Import Module %03d: %s \n", i + 1, pnstr);
+         nFunctions = GetImportFunctionNamesByModule (lpFile, pnstr, &pfNameBuff);
+         pnstr += strlen ((char *) (pnstr)) + 1;
+         pst = pfNameBuff;
+         for (j = 0; j < nFunctions; j++)
+           {
+             printf ("\nAddr:%08X hint(%04X) Name: %s",
+                     (*(int *) pst), (*(short *) (pst + 4)),
+             //(pst+6));
+                     TranslateFunctionName (pst + 6));
+             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++)
+       {
+         printf ("\nAddr:%08X Ord:%4d (%04Xh) Name: %s",
+              (*(int *) pst), (*(WORD *) (pst + 4)), (*(WORD *) (pst + 4)),
+         //(pst+6));
+                 TranslateFunctionName (pst + 6));
+         pst += strlen ((char *) (pst + 6)) + 6 + 1;
+       }
+      free ((void *) peNameBuff);
+    }
+
+  free ((void *) lpFile);
+
+  return 0;
+}
+
+
+/* EOF */