//
//
// This program was written by Sang Cho, associate 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
//
// date of second release: August 30, 1998 (alpha version)
//
//
//      you can contact me: e-mail address: sangcho@alpha94.chongju.ac.kr
//                            hitel id: chokhas
//                        phone number: (0431) 229-8491    +82-431-229-8491
//
//            real address: Sang Cho
//                      Computer and Information Engineering
//                      ChongJu University
//                      NaeDok-Dong 36 
//                      ChongJu 360-764
//                      South Korea
//
//   Copyright (C) 1997, 1998                            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. )

# include "disasm.h"

#define VOID                void
#define BOOLEAN             boolean
#define FALSE               0
#define TRUE                1
#define CONST               const
#define LOWORD(l)           ((WORD)(l))
#define WINAPI

//
// 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;

//                                       
// BitmapInfoHeader used in DIB Header (Icons, Cursors, Group ...s)
//

typedef struct tagBITMAPINFOHEADER {    /* bmih */
    DWORD   biSize;
    LONG    biWidth;
    LONG    biHeight;
    WORD    biPlanes;
    WORD    biBitCount;
    DWORD   biCompression;
    DWORD   biSizeImage;
    LONG    biXPelsPerMeter;
    LONG    biYPelsPerMeter;
    DWORD   biClrUsed;
    DWORD   biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

typedef struct tagRGBQUAD {     /* rgbq */
    BYTE    rgbBlue;
    BYTE    rgbGreen;
    BYTE    rgbRed;
    BYTE    rgbReserved;
} RGBQUAD, *PRGBQUAD;

// Icon Resources       ... addes by Sang Cho

typedef struct ICONDIR {
    WORD          idReserved;
    WORD          idType;
    WORD          idCount;
//ICONDIRENTRY idEntries[1];
} ICONHEADER, *PICONHEADER;

struct IconDirectoryEntry {
    BYTE  bWidth;
    BYTE  bHeight;
    BYTE  bColorCount;
    BYTE  bReserved;
    WORD  wPlanes;
    WORD  wBitCount;
    DWORD dwBytesInRes;
    DWORD dwImageOffset;
} ICONDIRENTRY, *PICONDIRENTRY;


//  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, 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 *);
int    WINAPI GetPreviousParamString (char *, char *);
int    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 **,int);

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


/* copy dos header information to structure */
BOOL  WINAPI GetDosHeader (
    LPVOID               lpFile,
    PIMAGE_DOS_HEADER    pHeader)
{
    /* dos header rpresents first structure of bytes in file */
    if (*(USHORT *)lpFile == IMAGE_DOS_SIGNATURE)
    memcpy((LPVOID)pHeader, lpFile, sizeof (IMAGE_DOS_HEADER));
    else
    return FALSE;

    return TRUE;
}

/* 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)
    memcpy((LPVOID)pHeader,  PEFHDROFFSET (lpFile), 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)
    memcpy ((LPVOID)pHeader,  OPTHDROFFSET (lpFile), 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 == 0) return 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 0;

    /* 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 */
            memcpy ((LPVOID)sh, (LPVOID)psh, 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?? */
    int               pidTab[1024];
    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);
        pidTab[nCnt] = (int)pid;
        nSize += strlen (pModule[nCnt]) + 1 + 4;

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

    /* copy all strings to one chunk of memory */
    *pszModules = (char *)calloc(nSize, 1);
    piNameBuffSize = nSize;
    psz = *pszModules;
    for (i=0; i<nCnt; i++)
    {
        *(int *)psz = pidTab[i]; 
        strcpy (psz+4, pModule[i]);
        psz += strlen (psz+4) + 1 + 4;
    }
    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;
    
    //
    // 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..................
    //
    
    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;
    int              r,rr;
    _key_            k;


    pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)(*(DWORD *)pszModule);

    /* 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+4);
    mnlength = strlen (pszModule+4);
    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
    
    //fprintf(stderr,"pid = %08X dwFunctionName = %08X name = %s", 
    //(int)pid-(int)lpFile, dwFunctionName,name),getch();

    // modified by sang cho 1998.1.24

    if (dwFunctionName==0) dwFunctionName = pid->dwRVAFunctionAddressList;

    while (dwFunctionName &&
       *(pdw=(DWORD *)GetActualAddress (lpFile, dwFunctionName)) )      
    {
        if ((*pdw) & 0x80000000 )   nSize += mnlength + 11 + 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;
    // modified by sang cho 1998.1.24
    if (dwFunctionName==0) dwFunctionName = pid->dwRVAFunctionAddressList;
    dwFunctionAddress = pid->dwRVAFunctionAddressList;
    while (dwFunctionName                          &&
       *(pdw=(DWORD *)GetActualAddress (lpFile, dwFunctionName)) )
    {
        if ((*pdw) & 0x80000000)
        {
        r=*(int *)psz=(int)(*(DWORD *)GetActualAddress (lpFile, dwFunctionAddress));
            psz += 4;
        *(short *)psz=*(short *)pdw;
        psz += 2;        rr=(int)pdw;
        sprintf(buff, "%s:NoName%04d", name, nnid++);
        strcpy (psz, buff);     psz += strlen (buff) + 1;
            // this one is needed to link import function names to codes..
            k.class=992; k.c_ref= r; k.c_pos=-rr;
            MyBtreeInsertX(&k);
            k.class=0; k.c_ref=-rr; k.c_pos=(int)pszModule+4;
            MyBtreeInsertX(&k);
        }
        else
        {
        r=*(int *)psz=(int)(*(DWORD *)GetActualAddress (lpFile, dwFunctionAddress));
            psz += 4;
        *(short *)psz=(*(short *)GetActualAddress(lpFile, *pdw));
        psz += 2;        rr=(int)GetActualAddress(lpFile, *pdw + 2);
        strcpy (psz, (char *)rr);
        psz += strlen ((char *)GetActualAddress(lpFile, *pdw + 2)) + 1;
        
            // this one is needed to link import function names to codes..
            k.class=991; k.c_ref= r; k.c_pos=rr;
            MyBtreeInsertX(&k);
            k.class=0; k.c_ref=rr; k.c_pos=(int)pszModule+4;
            MyBtreeInsertX(&k);
        }
        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 */
int   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 = %02X %s", *pin, pin); 
	      return (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"); return (0); }

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

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

/* translate parameter part of condensed name */
int   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 1;
        case 'q':
            *pout++ = '('; pin++;
            *ps++ = 'q';
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
        case 'r':
            if (*(pin+1) == 'p') { *ps++ = 'r'; pin += 2; }
            else { *ps++ = '&'; pin++; }
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
        // repeat processing
        case 't':
            if (isdigit(*(pin+1)))
            { 
                n = *(pin+1) - '0'; pin++; pin++;
                if (GetPreviousParamString (pout, name))
				{
                    strcpy (pout, name); pout += strlen (name);
                    for (i=1; i<n; i++)
                    {
                        *pout++ = ',';
                        strcpy (pout, name); pout += strlen (name);
                    }
                }
				else return 0;
			}
            else pin++;
            break;
        // prefix processing
        case 'u':
            strcpy (pout, "u");        pout +=  1; pin++;  
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
        case 'x':
            strcpy (pout, "const ");   pout +=  6; pin++;  
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
        case 'z':
            strcpy (pout, "static ");  pout +=  7; pin++;  
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
        default:  strcpy (pout, "!1!");pout +=  3; *pout++=*pin++;
            *ppin = pin; *ppout = pout; *pps = ps;
            return 1;
    }
    // need to process postfix finally
    c = *(ps-1);
    if (strchr ("tqx", c))
    { if (*(pin)&& !strchr( "@$%", *(pin))) *pout++ = ','; 
      *ppin = pin; *ppout = pout; *pps = ps; return 1; }
    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;
	return 1;
}

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

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

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

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

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

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

/* translate condesed import function name */
LPVOID WINAPI TranslateFunctionName (
    char      *psz)
{
    
    
    int                                 i, n;
    char                    c, cc;

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

    int                     is=0;
    char                    pStack[32]; // parameter processing stack
    Str_P                   sStack[32]; // String processing stack
    Str_P                   tok;        // String token
    Str_P                   c_str;      // current string 

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

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

    if (*psz != '@') return psz;
    pin  = psz;
    pout = buff;
    ps   = pStack;
    
    //................................................................
    // serious users may need to run the following code.
    // so I may need to include some flag options...
    // If you want to know about how translation is done,
    // you can just revive following line and you can see it.
    //                                                 october 6, 1997 ... sang cho
    //printf ("\n................................... %s", psz); // for debugging...
    
    //pa = pb = pout;
    pin++;                                             
    tok.flag = 'A'; tok.pos = pout; tok.length = 0;     tok.wasString = stringMode;
    sStack[is++] = tok;       // initialize sStack with dummy marker
    
    while (*pin)
    {
        while (*pin)
        {
        c = *pin;

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

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

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

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

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

                    stringMode = tok.wasString;

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

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

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

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

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

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

            else                 // parameter processing
            {
                if (!isdigit (c)) 
				{
				    if(!TranslateParameters (&pin, &pout, &ps)) return psz;
                }
				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[40960]={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);
        peNameBuffSize=nCnt;
        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;
    }       
    if (nCnt==0)
    {
    // get the number of unnamed functions
         nCnt += 18*(int)ped->NumberOfFunctions;
    /* allocate memory  for function names */
        *pszFunctions = (char *)calloc (nCnt, 1);
         peNameBuffSize=nCnt;
         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;
	PBYTE                              pMem;
	PWORD                              pw;
    char                    buff[32];
    int                                nCnt, i, j, n;
    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->NumberOfNamedEntries * 256 + prdRoot->NumberOfIdEntries * (32);
    *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->NumberOfNamedEntries; i++)
    {
		pw = (PWORD)((DWORD)prdRoot + (prde->Name ^ 0x80000000));

        if (!isalpha(*(PBYTE)pw))
		{
		    n=(int)(*(PBYTE)pw++); 
			for(j=0;j<n;j++)*pMem++ = *(PBYTE)pw++; 
			*pMem=0; pMem++;    
		}
		else
		{
			while(*pw) *pMem++ = *(PBYTE)pw++; 
			*pMem=0; pMem++;
		}
        prde++;
    }

    /* 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", (int)prdeName);
                 strcpy(pMem, buff);              pMem+=20;}
        prde++;
    }

    return prdRoot->NumberOfNamedEntries+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)
{
    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
		
		while (*pwd) {(*len)++; pwd++;}
        (*len)++;                             // name and null character
        pwd++;                               // skip double null
        
		*pMenu = pwd;
        return (int)flag;
	}
    else 
    {
        ispopup = flag;

        while (*pwd) {(*len)++; pwd++;}
        (*len)++;                             // name and null character
        pwd++;                               // skip double null
                       // popup node: need to go on...
        while (1)
        {       
            *pMenu = pwd;
            flag1 = (WORD)MenuScan (len, pMenu);
            pwd = *pMenu;
            if (flag1 & 0x0080) break; 
        }
        *pMenu = pwd;
        return flag;
    }
}

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

/* copy menu information */
int     WINAPI MenuFill (
    char      **psz,
    WORD      **pMenu)
{
    char      *ptr;
    WORD      *pwd;
    WORD       flag, flag1;
    WORD       id;

    ptr = *psz;
    pwd = *pMenu;
   
    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++;

		while (*pwd)                                             // name extract
        {
            *ptr = *(char *)pwd;
			if(!isprint(*ptr)) *ptr='.';
            ptr++; pwd++;
        } //name and null character
        *ptr=0;
        ptr++;
        pwd++;   		                // skip double null
		
		*pMenu = pwd;
        *psz = ptr;
        return (int)flag;
    }
    else 
    {
        *(WORD *)ptr = flag;             // flag store
        ptr += 2;
   
        while (*pwd)                     // name extract
        {
            *ptr = *(char *)pwd;
			if(!isprint(*ptr)) *ptr='.';
            ptr++; pwd++;
        } //name and null character
        *ptr=0;
        ptr++;
        pwd++;                          // skip double null
   
                     // 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; 
        }
    
        *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_MENU_HEADER                 pMenuHeader;
    PIMAGE_POPUP_MENU_ITEM             pPopup;
    char                    buff[256];
    int                     i,j; 
    int                     size;
    int                     sLength, nMenus;
    WORD                    flag;
    WORD                   *pwd;
    char                   *pMem;


    /* 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) 
		   + prdType->NumberOfNamedEntries*8);
 
    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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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, 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 PrintMenu1 (
    int         indent,
    char      **psz)
{
    
    int                     j, k, l;
    WORD                    id; //, num;
    WORD                    flag, flag1;
    char                    buff[128];
    char                   *ptr;

	ptr = *psz;
	flag = *(WORD *)ptr;
	ptr += 2;
	if ((flag&0x0010)==0x0000)
	{
	    printf ("\n");
        for (j=0; j<indent; j++) printf (" ");
        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;
		return (int)flag;
	}
	else
	{
	    printf ("\n");
		printf ("%s  {Popup}",ptr);
		ptr += strlen (ptr) + 1;
        *psz = ptr;
	
		while (1)
        {       
            *psz = ptr;
			flag1=(WORD)PrintMenu1 (indent+5, psz);
            ptr = *psz;
            if (flag1 & 0x0080) break; 
        }
	    *psz = ptr;
        return (int)flag;
	}
}

//
// This function is written by sang cho
//                                                         September 4, 1998

/* print contents of menu */
int     WINAPI PrintMenu (
    int         indent,
    char      **psz)
{
    WORD                    flag;
	
	while (1)
    {       
	    flag=(WORD)PrintMenu1 (indent, psz);
		if (flag & 0x0080) break; 
    }
    return (int)flag;
}


//
// 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 1;
}

//
// 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;
    char                    buff[32];
    int                     i,j; 
    int                     size;
    int                     sLength, nDialogs;
    //WORD                    flag;
    WORD                   *pwd;
    char                   *pMem; 


    /* 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)
		   + prdType->NumberOfNamedEntries*8);
 
    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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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) 
		{ if(isprint(*ptr))printf("%c", *ptr); else printf("."); ptr+= 2; } 
        ptr += 2;
        printf ("%c", '"');
    }
    *psz = ptr;
	return 1;
}

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

/* print contents of dialog */
int     WINAPI PrintDialog (
    char      **psz)
{    
    int                     i; 
    int                     num, size;
    DWORD                   flag;
    WORD                    class;
    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);
    }

    *psz = pmax;
	return 1;
}
 
//
// This function is written by sang cho
//                                                         September 5, 1998

/* scan string and copy string */
int     WINAPI GetContentsOfString (
    LPVOID    lpFile,
    char      **pszResTypes)
{
    PIMAGE_RESOURCE_DIRECTORY          prdType, prdName, prdLanguage;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY    prde, prde1;
    PIMAGE_RESOURCE_DIR_STRING_U       pStringName;
    PIMAGE_RESOURCE_DATA_ENTRY         prData;
    PWORD                              pStringHeader;
    char                    buff[256];
    int                     i,j; 
    int                     size;
    int                     sLength, nStrings;
    WORD                   *pwd;
    char                   *pMem; 

    /* 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)
		   + prdType->NumberOfNamedEntries*8);
 
    for (i=0; i<prdType->NumberOfIdEntries; i++)
    {
    if (prde->Name == RT_STRING) break;
    prde++;
    }
    if (prde->Name != RT_STRING) 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));


    nStrings=prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
    sLength=0;
    
    for (i=0; i<prdName->NumberOfNamedEntries; i++)
    {
        pStringName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        sLength += pStringName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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++)
    {
        pStringName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        
        
        for (j=0; j<pStringName->Length; j++)
            *pMem++ = (char)(pStringName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        pStringHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
     
        
        
        pwd = pStringHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }
    for (i=0; i<prdName->NumberOfIdEntries; i++)
    {
        
        sprintf (buff, "StringId_%04X", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) 
        {   printf ("\nprData = NULL"); exit (0); }

        pStringHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
        
        
        pwd = pStringHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }

    return nStrings;
}

//
// This function is written by sang cho
//                                                         September 5, 1998

/* print contents of string */
int     WINAPI PrintString (
    char      **psz)
{    
    int                     i; 
	int                     num, size;
    char                    *ptr, *pmax;

    ptr  = *psz;
    size = *(int *)ptr;
    ptr += 4;
    pmax = ptr+size;
    
   	while (ptr<pmax)
	{
		num=*ptr;
		ptr+=2;
	   
	    i=0;   if(num<0) num+=256;
		if (num>0) {printf ("\n    ");  printf ("%c",'"');}
        while (i<num) 
		{ 
		    if  (*ptr==0x09) printf("<t>");
			else if	(*ptr==0x0D && *(ptr+2)==0x0A) {printf("<nl>"); ptr+=2; i++;}
			else if (isprint(*ptr)) printf("%c", *ptr);
			else printf(".");
			ptr+= 2; i++;
		}
        if (num>0) printf ("%c", '"');
    }
    
    *psz = pmax;
	return 1;
}

//
// This function is written by sang cho
//                                                         September 6, 1998

/* scan icon and copy icon */
int     WINAPI GetContentsOfIcon (
    LPVOID    lpFile,
    char      **pszResTypes)
{
    PIMAGE_RESOURCE_DIRECTORY          prdType, prdName, prdLanguage;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY    prde, prde1;
    PIMAGE_RESOURCE_DIR_STRING_U       pIconName;
    PIMAGE_RESOURCE_DATA_ENTRY         prData;
    PWORD                              pIconHeader;
    char                    buff[256];
    int                     i,j; 
    int                     size;
    int                     sLength, nIcons;
    WORD                   *pwd;
    char                   *pMem; 

    /* 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)
		   +prdType->NumberOfNamedEntries*8);
 
    for (i=0; i<prdType->NumberOfIdEntries; i++)
    {
    if (prde->Name == RT_ICON) break;
    prde++;
    }
    if (prde->Name != RT_ICON) 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));


    nIcons=prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
    sLength=0;
    
    for (i=0; i<prdName->NumberOfNamedEntries; i++)
    {
        pIconName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        sLength += pIconName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        size = prData->Size; 
        sLength += 4+size;       
        prde++;
    }
    //
    // allocate memory for icon 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++)
    {
        pIconName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        
        
        for (j=0; j<pIconName->Length; j++)
            *pMem++ = (char)(pIconName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        pIconHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
     
        
        
        pwd = pIconHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }
    for (i=0; i<prdName->NumberOfIdEntries; i++)
    {
        
        sprintf (buff, "IconId_%04X", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) 
        {   printf ("\nprData = NULL"); exit (0); }

        pIconHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
        
        
        pwd = pIconHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }

    return nIcons;
}

//
// This function is written by sang cho
//                                                         September 6, 1998

/* print contents of icon */
int     WINAPI PrintIcon (
    char      **psz)
{    
    int                     i; 
	int                     j,k,l,n,c;
	int                     h,w,nc,ww;
	//char                    buff[256];
	int                     a[256][256];
	int                     m[256][256];
	int                     color[256];
	char *                  show[]=
	{"  ",". "," .","+,",", ",",+","'+","aa","^^","+!","!!","#$","!/","@$","$$","##"};
	int                     size; //num
    char                    *ptr, *pmax;
	unsigned char           r,g,b;

    ptr  = *psz;
    size = *(int *)ptr;
	pmax = ptr+size+4;

	n    = *(int *)(ptr+4);
	h    = *(int *)(ptr+12); h/=2;
	w    = *(int *)(ptr+ 8); 
	l    = *(short *)(ptr + 18);
	nc   = 1; for(i=0;i<l;i++)nc*=2;
	ww   = (w+(8/l)-1)/(8/l); ww=(ww+3)/4; ww=ww*4;

	//fprintf(stderr,"\nprintIcon h=%d w=%d nc=%d ",h,w,nc);getch();

    if(h>0 && h<256)
    {
	
        ptr += (n+4);
	    for (i=0;i<nc;i++)
	    {
	        r=*ptr++;g=*ptr++;b=*ptr++;ptr++;
		    c=r+g+b;
		         if (c==0) color[i]=15;
		    else if (c<=128)
		    {
		        if(r>g&&r>b) color[i]=11;else
			    if(g>r&&g>b) color[i]=13;else color[i]=14;
		    }
		    else if (c==255)
		    {
		        if(r>g&&r>b) color[i]=3;else
			    if(g>r&&g>b) color[i]=5;else color[i]=6;
		    }
		    else if (c==256)
		    {
		        if(r<g&&r<b) color[i]=12;else
			    if(g<r&&g<b) color[i]=10;else color[i]=9;
		    }
		    else if (c<=384) color[i]=7;
		    else if (c<=510)
		    {    
		        if(r<g&&r<b) color[i]=4;else
			    if(g<r&&g<b) color[i]=2;else color[i]=1;
		    }
		    else if (c<=576) color[i]=8;
		    else             color[i]=0;
	    }
	    for (i=0;i<h;i++)
	    {
	        for (j=0;j<ww;j++)
		    {
		        b=*ptr++;
				if (l==8) {
				a[h-1-i][j]  = b;
		        		  }
			    else if (l==4) {
				a[h-1-i][j+j]  = b / 16;
			    a[h-1-i][j+j+1]= b % 16;
		        		  }
				else if(l==2)
				          {
			    for (k=0;k<4;k++) 
			    {
			        r=(b>>(6-2*k))&0x03;
				    if      (r==0x03) a[h-1-i][4*j+k]=15; 
					else if (r==0x02) a[h-1-i][4*j+k]=10;
					else if (r==0x01) a[h-1-i][4*j+k]=5;
					else              a[h-1-i][4*j+k]=0;
				}
				          }
				else if(l==1)
				          {
			    for (k=0;k<8;k++) 
			    {
			        if ((b>>(7-k))&0x01)
				    a[h-1-i][8*j+k]=15; else a[h-1-i][8*j+k]=0;
			    }
				          }
				else a[i][j]=0;
			}
	    }
	    for (i=0;i<h;i++)
	    {
	        for (j=0;j<w/8;j++)
		    {
		        b=*ptr++;
			    for (k=0;k<8;k++) 
			    {
			        if ((b>>(7-k))&0x01)
				    m[h-1-i][8*j+k]=1; else m[h-1-i][8*j+k]=0;
			    }
		    }
	    }
    }

	printf("   height=%3d  width=%3d  # of bits=%3d ", h, w, l);
	if (moreprint)
	{
	    printf("\n\n");
		for (i=0;i<h;i++)
	    {
	        for (j=0;j<w;j++)
		    {
		        if (color[a[i][j]]<15) printf("%s",show[color[a[i][j]]]);
			    else if (m[i][j])      printf("#~"); else printf("##");
		    }
		    printf("\n");
	    }
	}

	*psz=pmax;
	return 1;
}

//
// This function is written by sang cho
//                                                         September 10, 1998

/* scan bitmap and copy bitmap */
int     WINAPI GetContentsOfBitmap (
    LPVOID    lpFile,
    char      **pszResTypes)
{
    PIMAGE_RESOURCE_DIRECTORY          prdType, prdName, prdLanguage;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY    prde, prde1;
    PIMAGE_RESOURCE_DIR_STRING_U       pBitmapName;
    PIMAGE_RESOURCE_DATA_ENTRY         prData;
    PWORD                              pBitmapHeader;
    char                    buff[256];
    int                     i,j; 
    int                     size;
    int                     sLength, nBitmaps;
    WORD                   *pwd;
    char                   *pMem; 

    /* 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)
		   +prdType->NumberOfNamedEntries*8);
 
    for (i=0; i<prdType->NumberOfIdEntries; i++)
    {
    if (prde->Name == RT_BITMAP) break;
    prde++;
    }
    if (prde->Name != RT_BITMAP) 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));


    nBitmaps=prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
    sLength=0;
    
    for (i=0; i<prdName->NumberOfNamedEntries; i++)
    {
        pBitmapName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        sLength += pBitmapName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        size = prData->Size; 
        sLength += 4+size;       
        prde++;
    }
    //
    // allocate memory for bitmap 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++)
    {
        pBitmapName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        
        
        for (j=0; j<pBitmapName->Length; j++)
            *pMem++ = (char)(pBitmapName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        pBitmapHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
     
        
        
        pwd = pBitmapHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }
    for (i=0; i<prdName->NumberOfIdEntries; i++)
    {
        
        sprintf (buff, "BitmapId_%04X", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) 
        {   printf ("\nprData = NULL"); exit (0); }

        pBitmapHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
        
        
        pwd = pBitmapHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }

    return nBitmaps;
}

//
// This function is written by sang cho
//                                                         September 10, 1998

/* print contents of bitmap */
int     WINAPI PrintBitmap (
    char      **psz)
{    
    int                     i;
	int                     noprint=0;
	int                     j,k,l,n,c,e;
	int                     h,w,nc,ww;
	//char                    buff[256];
	int                     a[512][512];
	int                     color[256];
	char *                  show[]=
	{"  ",". "," .","+,",", ",",+","'+","aa","^^","+!","!!","#$","!/","@$","$$","##"};
	int                     size; //num
    char                    *ptr, *pmax;
	unsigned char           r,g,b;

    ptr  = *psz;
    size = *(int *)ptr;
	pmax = ptr+size+4;

	n    = *(int *)(ptr+4);
	if (n==12) // strange form
	{
	    h=*(short*)(ptr+10);
		w=*(short*)(ptr+8);
		l=*(short*)(ptr+12);
		nc=1; for(i=0;i<l;i++)nc*=2;
	}
	else
	{
	    h    = *(int *)(ptr+12); 
	    w    = *(int *)(ptr+ 8); 
	    l    = *(short *)(ptr + 18);
	    e    = *(int *)(ptr+20);
	    nc   = 1; for(i=0;i<l;i++)nc*=2;
	}
	if (0<l && l<=8) ww   = (w+(8/l)-1)/(8/l); else ww=ww*4;
	ww=(ww+3)/4; ww=ww*4;

	//fprintf(stderr,"\nprintBitmap h=%d w=%d nc=%d size=%d",h,w,nc,size);getch();

    if(h>0 && h<512 && l<=8 && 12<n)
    {
	
        ptr += (n+4);
	    for (i=0;i<nc;i++)
	    {
	        r=*ptr++;g=*ptr++;b=*ptr++;ptr++;
		    c=r+g+b;
		         if (c==0) color[i]=15;
		    else if (c<=128)
		    {
		        if(r>g&&r>b) color[i]=11;else
			    if(g>r&&g>b) color[i]=13;else color[i]=14;
		    }
		    else if (c==255)
		    {
		        if(r>g&&r>b) color[i]=3;else
			    if(g>r&&g>b) color[i]=5;else color[i]=6;
		    }
		    else if (c==256)
		    {
		        if(r<g&&r<b) color[i]=12;else
			    if(g<r&&g<b) color[i]=10;else color[i]=9;
		    }
		    else if (c<=384) color[i]=7;
		    else if (c<=510)
		    {    
		        if(r<g&&r<b) color[i]=4;else
			    if(g<r&&g<b) color[i]=2;else color[i]=1;
		    }
		    else if (c<=576) color[i]=8;
		    else             color[i]=0;
	    }
		if (e==0)
		{
	        for (i=0;i<h;i++)
	        {
	            for (j=0;j<ww;j++)
		        {
		            b=*ptr++;
				    if (l==8) 
					{
				        a[h-1-i][j]  = b;
		        	}
			        else if (l==4) 
					{
				        a[h-1-i][j+j]  = b / 16;
			            a[h-1-i][j+j+1]= b % 16;
		        	}
				    else if(l==2)
				    {
			            for (k=0;k<4;k++) 
			            {
			                r=(b>>(6-2*k))&0x03;
				            if      (r==0x03) a[h-1-i][4*j+k]=15; 
					        else if (r==0x02) a[h-1-i][4*j+k]=10;
					        else if (r==0x01) a[h-1-i][4*j+k]=5;
					        else              a[h-1-i][4*j+k]=0;
				        }
				    }
				    else if(l==1)
				    {
			            for (k=0;k<8;k++) 
			            {
			                if ((b>>(7-k))&0x01)
				            a[h-1-i][8*j+k]=15; else a[h-1-i][8*j+k]=0;
			            }
				    }
				    else a[h-1-i][j]=0;
			    }
	        }
		}
		else
		{
		    if (l==8)
			{
			    i=h-1;j=0;
				while(ptr<pmax)
				{
				    r=*ptr++; g=*ptr++;
				    if(r>0)					   // repeat mode (normal)
				    {
				        for(k=0;k<r;k++) 
						{
						    a[i][j++]=g; 
				        }
					}
					else
					{
					    if(g==0) {i--;j=0;}		// end of line
						else if (g==1) break;	// end of bitmap
						else if (g==2) 			// delta
						{
						    r=*ptr++; g=*ptr++;
							j+=r; i-=g;
						}
						else					// absolute mode
						{
						    for(k=0;k<g;k++) 
						    {
						        r=*ptr++; b=*ptr++;
								a[i][j++]=r; 
							    k++; if (k>=g) break;
							    a[i][j++]=b;
				            }
						}
					}
				}
			}
			else if (l==4)
			{
			    i=h-1;j=0;
				while(ptr<pmax)
				{
				    r=*ptr++; g=*ptr++;
				    if(r>0)					   // repeat mode (normal)
				    {
				        for(k=0;k<r;k++) 
						{
						    a[i][j++]=g/16; 
							k++; if (k>=r) break;
							a[i][j++]=g%16;    
				        }
					}
					else
					{
					    if(g==0) {i--;j=0;}		// end of line
						else if (g==1) break;	// end of bitmap
						else if (g==2) 			// delta
						{
						    r=*ptr++; g=*ptr++;
							j+=r; i-=g;
						}
						else					// absolute mode
						{
						    for(k=0;k<g;k++) 
						    {
						        r=*ptr++; b=*ptr++;
								a[i][j++]=r/16; 
							    k++; if (k>=g) break;
							    a[i][j++]=r%16;
								k++; if (k>=g) break;
								a[i][j++]=b/16; 
							    k++; if (k>=g) break;
							    a[i][j++]=b%16;
				            }
						}
					}
				}
			}
			else noprint=1;
		}    
    }
	else noprint=1;
	
	printf("   height=%3d  width=%3d  # of bits=%3d ", h, w, l);
	if (moreprint && !noprint)
	{
	    printf("\n\n");
		for (i=0;i<h;i++)
	    {
	        for (j=0;j<w;j++)
		    {
		        printf("%s",show[color[a[i][j]]]);
		    }
		    printf("\n");
	    }
	}

	*psz=pmax;
	return 1;
}


//
// This function is written by sang cho
//                                                         September 9, 1998

/* scan cursor and copy cursor */
int     WINAPI GetContentsOfCursor (
    LPVOID    lpFile,
    char      **pszResTypes)
{
    PIMAGE_RESOURCE_DIRECTORY          prdType, prdName, prdLanguage;
    PIMAGE_RESOURCE_DIRECTORY_ENTRY    prde, prde1;
    PIMAGE_RESOURCE_DIR_STRING_U       pCursorName;
    PIMAGE_RESOURCE_DATA_ENTRY         prData;
    PWORD                              pCursorHeader;
    char                    buff[256];
    int                     i,j; 
    int                     size;
    int                     sLength, nCursors;
    WORD                   *pwd;
    char                   *pMem; 

    /* 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)
		   +prdType->NumberOfNamedEntries*8);
 
    for (i=0; i<prdType->NumberOfIdEntries; i++)
    {
        if (prde->Name == RT_CURSOR) break;
        prde++;
    }
    if (prde->Name != RT_CURSOR) 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)
		   +prdName->NumberOfNamedEntries*8);


    nCursors=prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
	sLength=0;
    
    for (i=0; i<prdName->NumberOfNamedEntries; i++)
    {
        pCursorName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        sLength += pCursorName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        size = prData->Size; 
        sLength += 4+size;       
        prde++;
    }
	
    //
    // allocate memory for cursor names
    //
    *pszResTypes = (char *)calloc (sLength, 1);

    pMem = *pszResTypes;
    //
    // and start all over again
    //
    prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
           ((DWORD)prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)
		   +prdName->NumberOfNamedEntries*8);

    for (i=0; i<prdName->NumberOfNamedEntries; i++)
    {
        pCursorName = (PIMAGE_RESOURCE_DIR_STRING_U) 
              ((DWORD)prdType + (prde->Name ^ 0x80000000));
        
        
        for (j=0; j<pCursorName->Length; j++)
            *pMem++ = (char)(pCursorName->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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) continue;
        
        pCursorHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
     
        
        
        pwd = pCursorHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }
	
    for (i=0; i<prdName->NumberOfIdEntries; i++)
    {
        
        sprintf (buff, "CursorId_%04X", (int)(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)
			+prdLanguage->NumberOfNamedEntries*8);
        
        prData = (PIMAGE_RESOURCE_DATA_ENTRY)
             ((DWORD)prdType + prde1->OffsetToData);
        if (prData == NULL) 
        {   printf ("\nprData = NULL"); exit (0); }

        pCursorHeader =  (PWORD)
                 GetActualAddress (lpFile, prData->OffsetToData);
        
        
        pwd = pCursorHeader;
        size = prData->Size;
        *(int *)pMem = size;          pMem += 4;
        StrangeMenuFill (&pMem, &pwd, size);
        
        prde++;
    }
    return nCursors;
}

//
// This function is written by sang cho
//                                                         September 9, 1998

/* print contents of cursor */
int     WINAPI PrintCursor (
    char      **psz)
{    
    int                     i; 
	int                     j,k,l,n,c;
	int                     h,w,nc,ww;
	int                     x,y;
	//char                    buff[256];
	int                     a[256][256];
	int                     m[256][256];
	int                     color[256];
	char *                  show[]=
	{"  ",". "," .","+,",", ",",+","'+","aa","^^","+!","!!","#$","!/","@$","$$","##"};
	int                     size; //num
    char                    *ptr, *pmax;
	unsigned char           r,g,b;

	/*
    ptr = *psz;
    printf("\n");
	size = *(int *)ptr;
	pmax = ptr+size+4;

    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;
	return 1;*/
	
	ptr  = *psz;
    size = *(int *)ptr;
	pmax = ptr+size+4;

	x    = *(short*)(ptr+4);
	y    = *(short*)(ptr+6);ptr+=4;
	n    = *(int *)(ptr+4);
	h    = *(int *)(ptr+12); h/=2;
	w    = *(int *)(ptr+ 8); 
	l    = *(short *)(ptr + 18);
	nc   = 1; for(i=0;i<l;i++)nc*=2;
	ww   = (w+(8/l)-1)/(8/l); ww=(ww+3)/4; ww=ww*4;

	//fprintf(stderr,"\nprintCursor h=%d w=%d nc=%d ",h,w,nc);getch();

    if(h>0 && h<256)
    {
	
        ptr += (n+4);
	    for (i=0;i<nc;i++)
	    {
	        r=*ptr++;g=*ptr++;b=*ptr++;ptr++;
		    c=r+g+b;
		         if (c==0) color[i]=15;
		    else if (c<=128)
		    {
		        if(r>g&&r>b) color[i]=11;else
			    if(g>r&&g>b) color[i]=13;else color[i]=14;
		    }
		    else if (c==255)
		    {
		        if(r>g&&r>b) color[i]=3;else
			    if(g>r&&g>b) color[i]=5;else color[i]=6;
		    }
		    else if (c==256)
		    {
		        if(r<g&&r<b) color[i]=12;else
			    if(g<r&&g<b) color[i]=10;else color[i]=9;
		    }
		    else if (c<=384) color[i]=7;
		    else if (c<=510)
		    {    
		        if(r<g&&r<b) color[i]=4;else
			    if(g<r&&g<b) color[i]=2;else color[i]=1;
		    }
		    else if (c<=576) color[i]=8;
		    else             color[i]=0;
	    }
	    for (i=0;i<h;i++)
	    {
	        for (j=0;j<ww;j++)
		    {
		        b=*ptr++;
				if (l==8) {
				a[h-1-i][j]  = b;
		        		  }
			    else if (l==4) 
				          {
				a[h-1-i][j+j]  = b / 16;
			    a[h-1-i][j+j+1]= b % 16;
		        		  }
				else if(l==2)
				          {
			    for (k=0;k<4;k++) 
			    {
			        r=(b>>(6-2*k))&0x03;
				    if      (r==0x03) a[h-1-i][4*j+k]=15; 
					else if (r==0x02) a[h-1-i][4*j+k]=10;
					else if (r==0x01) a[h-1-i][4*j+k]=5;
					else              a[h-1-i][4*j+k]=0;
				}
				          }
				else if(l==1)
				          {
			    for (k=0;k<8;k++) 
			    {
			        if ((b>>(7-k))&0x01)
				    a[h-1-i][8*j+k]=15; else a[h-1-i][8*j+k]=0;
			    }
				          }
				else a[i][j]=0;
			}
	    }
	    for (i=0;i<h;i++)
	    {
	        for (j=0;j<w/8;j++)
		    {
		        b=*ptr++;
			    for (k=0;k<8;k++) 
			    {
			        if ((b>>(7-k))&0x01)
				    m[h-1-i][8*j+k]=1; else m[h-1-i][8*j+k]=0;
			    }
		    }
	    }
    }
	printf("   height=%3d  width=%3d  # of bits=%3d (hotx=%d,hoty=%d)", 
		       h, w, l, x, y);
	if (moreprint)
	{
	    printf("\n\n");
		for (i=0;i<h;i++)
	    {
	        for (j=0;j<w;j++)
		    {
		        if (color[a[i][j]]<15) printf("%s",show[color[a[i][j]]]);
			    else if (m[i][j])      printf(".."); else printf("##");
		    }
		    printf("\n");
	    }
	}
	
	*psz=pmax;
	return 1;
}



/* 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
        memcpy (*pszModule, pdm->Data, 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)
    {
    memcpy ((LPVOID)psdh, (LPVOID)pdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER));
    return TRUE;
    }

    return FALSE;
}

void printTimeDateStamp(DWORD tds)
{
long long tem;
int      i, iyear, iweek, idate, ihour, isecond;
int      monthDays[] ={31,28,31,30,31,30,31,31,30,31,30,31};
char    *monString[] ={"Jan","Feb","Mar","Apr","May","Jun",  
	                   "Jul","Aug","Sep","Oct","Nov","Dec"};
char    *weekString[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

    // I don't have documentation about timedatestamp
	// so my best guess is to run some kind of reference software
	// Ida and dumppe gives different results 
	// I don't know which is right but I guess dumppe is right so 
	// I changed output accordingly.
	// If you think Ida is right then the following 8 should be 5.
	// 1998.2.27 sangcho
	tem  = (long long)tds;
	ihour=(int)(tem/3600)-8; isecond=(int)(tem%3600);
	idate=ihour/24; ihour=ihour%24;	 iweek=(idate+4)%7;
	iyear=idate/365; idate=idate-iyear*365;
	if (idate<(iyear+1)/4) {iyear=iyear-1; idate=idate+365;}
	idate -= (iyear+1)/4;  
	if ((iyear+2)%4==0) monthDays[1]+=1;
	for (i=0;i<11;i++)monthDays[i+1]=monthDays[i]+monthDays[i+1];
	for (i=0;i<12;i++)if (idate<monthDays[i]) break;
	if (i>0) idate-=monthDays[i-1];
	// summer time adjustment i hope this is right.	  1998.2.26 sangcho
	// daylight saving time is from the first sunday 2:00 Am of April to
	// the last sunday 2:00 Am of October
	     if ((3<i)&&(i<9)) ihour+=1; 
	else if (i==3)
	{
	          if (idate>6) ihour+=1;
		 else if (iweek==0){if (ihour>1) ihour+=1;}
		 else if (idate>=iweek) ihour+=1;
	}
	else if (i==9)
	{
	          if (idate<24) ihour+=1;
		 else if (iweek==0){if (ihour<2) ihour+=1;}
		 else if (idate<24+iweek) ihour+=1;
	}
	if (ihour>24) {ihour-=24; idate+=1;}
	if (idate+1>monthDays[i]) {idate-=monthDays[i];i+=1;}
	printf("T.DateStamp = %08X: ",(int)tds);
	printf("%s %s %02d %02d:%02d:%02d %4d\n", weekString[iweek], monString[i], 
	        idate+1, ihour, isecond/60, isecond%60, 1970+iyear);


}

/* I need to place these data here to keep integrity of codes */

LPVOID          lpFile;        /* pointer to the contents of the input file */
LPVOID          lpMap;         /* pointer to the map of codes processed */
LPVOID          lpMap1;        /* pointer to the map of codes processed */ 
int             nSections;              // number of sections
int             nResources;             // number of resources
int             nMenus;                 // number of menus
int             nDialogs;               // number of dialogs
int             nStrings;               // number of strings
int             nIcons;                 // number of icons
int             nCursors;               // number of cursors
int             nBitmaps;               // number of bitmaps
int             nAccelerators;          // number of accelerators
int             nImportedModules;       // number of imported modules
int             nFunctions;                     // number of functions in the imported module
int             nExportedFunctions;     // number of exported funcions
DWORD           imageBase;                      // image base of the file
DWORD           entryPoint;                     // entry point of the file
DWORD           imagebaseRVA;  /* imagebase + RVA of the code */
int             CodeOffset;    /* starting point of code   */
int             CodeSize;      /* size of code             */
int             vCodeOffset;    /* starting point of code   */
int             vCodeSize;      /* size of code             */
int             MapSize;       /* size of code map         */
DWORD           maxRVA;        /* the largest RVA of sections */
int             maxRVAsize;    /* size of that section */
int             moreprint=0;   /* need to print some more */

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   
char           *psNameBuff;       // string name buffer
char           *pcNameBuff;       // cursor name buffer
char           *pbNameBuff;       // bitmap name buffer
char           *pnNameBuff;       // icon   name buffer
char           *paNameBuff;       // accelerator name buffer
int             piNameBuffSize;   // import module name buffer
int             pfNameBuffSize;   // import functions in the module name buffer
int             peNameBuffSize;   // export function name buffer
int             pmNameBuffSize;   // menu name buffer
int             pdNameBuffSize;   // dialog name buffer

//
// 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 32
#define  MAXNAMESTRNUMBER 40

    IMAGE_SECTION_HEADER            shdr [MAXSECTIONNUMBER];

int pedump (int argc,char **argv)
{
    DWORD                           fileType;
    
    IMAGE_DOS_HEADER                dosHdr;
    PIMAGE_FILE_HEADER              pfh;
    PIMAGE_OPTIONAL_HEADER          poh;
    PIMAGE_SECTION_HEADER           psh;
    //IMAGE_SECTION_HEADER            idsh;
    extern     IMAGE_SECTION_HEADER    shdr[];
    //PIMAGE_IMPORT_MODULE_DIRECTORY  pid;

    int         i, j, n;
	int         CodeSize1;
	int         c, nexes;
	DWORD       tds;
	DWORD       baseofcode,baseofdata;

    char     *pnstr;
    char     *pst;

    //unsigned char          *p, *q;
    _key_                   k;
    //PKEY                    pk;

    GetDosHeader (lpFile, &dosHdr);

    if (dosHdr.e_magic == IMAGE_DOS_SIGNATURE)
    {
        if ((dosHdr.e_lfanew > 4096) || (dosHdr.e_lfanew < 64))
        {
    printf ("This file is not PE format ... sorry, it looks like DOS format\n");
    exit (0);
        }
    }
    else 
    {
    printf ("This doesn't look like executable file .. sorry, ...\n");
    exit (0);
    }

    fileType = ImageFileType (lpFile);

    if (fileType != IMAGE_NT_SIGNATURE) 
    {
        printf ("This file is not PE format ... sorry,\n");
        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;

    CodeSize = poh->SizeOfCode;

	tds = pfh->TimeDateStamp;
	
	printTimeDateStamp(tds);

    if (psh == NULL) return 0;

    /* store section headers */
    
	nexes=0;
    for (i=0; i < nSections; i++)
    {       
        shdr[i] = *psh++;
		 c=(int)shdr[i].Characteristics;
        if ((c&0x60000020)==0x60000020) nexes++; 
    }

	if (CodeSize==0) CodeSize=shdr[0].SizeOfRawData;

    // get Code offset and size, Data offset and size
    maxRVA = 0;

	baseofcode=poh->BaseOfCode;
	baseofdata=poh->BaseOfData;
	if (baseofcode>=baseofdata) baseofcode=0;
	//fprintf(stderr,"\npoh->BaseOfCode=%08X",poh->BaseOfCode);getch();

    for (i=0; i < nSections; i++)
    {       
        if (baseofcode == shdr[i].VirtualAddress 
		 || (baseofcode == 0 && i == 0))
        {
            imagebaseRVA = imageBase + shdr[i].VirtualAddress;
            CodeOffset = shdr[i].PointerToRawData;
            CodeSize1 = shdr[i].SizeOfRawData;
			if (nexes==1 && CodeSize!=CodeSize1) CodeSize=CodeSize1;
			printf("Code Offset = %08X, Code Size = %08X \n", 
            (int)(shdr[i].PointerToRawData), CodeSize);
        }
        if (shdr[i].VirtualAddress>maxRVA) 
        {
            maxRVA = shdr[i].VirtualAddress;
            maxRVAsize = shdr[i].SizeOfRawData;
        }
        if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040)
        //if (poh->BaseOfData == shdr[i].VirtualAddress)
        {
        printf ("Data Offset = %08X, Data Size = %08X \n",
            (int)(shdr[i].PointerToRawData), (int)(shdr[i].SizeOfRawData));
            break;
        }
    }
    for (   ; i < nSections; i++)
    {       
        if (shdr[i].VirtualAddress>maxRVA) 
        {
            maxRVA = shdr[i].VirtualAddress;
            maxRVAsize = shdr[i].SizeOfRawData;
        }
    }

    printf ("\n");
    
    printf ("Number of Objects = %04d (dec), Imagebase = %08Xh \n",
        nSections, (int)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, (int)(shdr[i].VirtualAddress), 
			(int)(shdr[i].PointerToRawData),
            (int)(shdr[i].SizeOfRawData), (int)(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);
        
		nCursors = GetContentsOfCursor (lpFile, &pcNameBuff);
        
        if (nCursors > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++ CURSOR INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			pst = pcNameBuff;
            printf ("\nNumber of Cursors = %4d (decimal)", nCursors);

            printf ("\n");

            for (i=0; i < nCursors; i++)
            {
                // Cursor ID print
                printf ("\nName: %s", pst);
                pst += (n=strlen (pst)) + 1;
				for(j=n;j<20;j++) printf(" ");
                PrintCursor (&pst);
            }                                                   
            free ((void *)pcNameBuff); 
		}

		nBitmaps = GetContentsOfBitmap (lpFile, &pbNameBuff);
        
        if (nBitmaps > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++ BITMAP INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			pst = pbNameBuff;
            printf ("\nNumber of Bitmaps = %4d (decimal)", nBitmaps);

            printf ("\n");

            for (i=0; i < nBitmaps; i++)
            {
                // Bitmap ID print
                printf ("\nName: %s", pst);
                pst += (n=strlen (pst)) + 1;
				for(j=n;j<20;j++) printf(" ");
                PrintBitmap (&pst);
            }                                                   
            free ((void *)pbNameBuff); 
		}

		nIcons = GetContentsOfIcon (lpFile, &pnNameBuff);
        
        if (nIcons > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++ ICON INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			pst = pnNameBuff;
            printf ("\nNumber of Icons = %4d (decimal)", nIcons);

            printf ("\n");

            for (i=0; i < nIcons; i++)
            {
                // Dialog ID print
                printf ("\nName: %s", pst);
                pst += (n=strlen (pst)) + 1;
				for(j=n;j<20;j++) printf(" ");
                PrintIcon (&pst);
            }                                                   
            free ((void *)pnNameBuff); 
		}


        nMenus = GetContentsOfMenu (lpFile, &pmNameBuff);
        
        if (nMenus > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++++ MENU INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			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");
        }

        nDialogs = GetContentsOfDialog (lpFile, &pdNameBuff);
        
        if (nDialogs > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++ DIALOG INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			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");
		}

        nStrings = GetContentsOfString (lpFile, &psNameBuff);
       
        if (nStrings > 0)
        {
            printf ("\n");
            printf ("\n+++++++++++++++++ STRING INFORMATION +++++++++++++++++++");
            printf ("\n");
			
			pst = psNameBuff;
            printf ("\nNumber of Strings = %4d (decimal)", nStrings);

            printf ("\n");

            for (i=0; i < nStrings; i++)
        {
                // String ID print
                printf ("\nName: %s", pst);
                pst += strlen (pst) + 1;
                PrintString (&pst);
        }                                                   
        }
        free ((void *)psNameBuff); 
        printf ("\n");
    }
    
    printf ("\n+++++++++++++++++++ IMPORTED FUNCTIONS +++++++++++++++++++\n");

    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 + 4);
        pnstr += strlen ((char *)(pnstr+4)) + 1 + 4;
        }
        
        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 + 4);
            nFunctions = GetImportFunctionNamesByModule (lpFile, pnstr, &pfNameBuff);
            pnstr += strlen ((char *)(pnstr+4)) + 1 + 4;
            pst = pfNameBuff;
            for (j=0;j < nFunctions;j++)
            {
            printf ("\nAddr:%08X hint(%04X) Name: %s",
                    (*(int *)pst),(*(short *)(pst+4)), 
                        //(pst+6));
                        (char*)TranslateFunctionName(pst+6));
                pst += strlen ((char *)(pst+6)) + 1 + 6;
            }
            free ((void *)pfNameBuff);
        }
        //free ((void *)piNameBuff);
    }
    
    printf("\n");
    printf("\n+++++++++++++++++++ EXPORTED FUNCTIONS +++++++++++++++++++\n");

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

    MapSize = CodeSize + CodeOffset;
    lpMap = (void *) calloc (MapSize, 1);
    lpMap1 = (void *)calloc (MapSize, 1);
    if (lpMap==NULL || lpMap1==NULL) 
    {
        fprintf(stderr,"cannot allocate memory.");exit(0);
    }

    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));
                   (char*)TranslateFunctionName(pst+6));
            // this one is needed to link export function names to codes..
            k.class=2048; k.c_ref= *(int *)pst; k.c_pos=0;
            if (AddressCheck(k.c_ref))
            {
                MyBtreeInsertEx(&k);
                if(isGoodAddress(k.c_ref))
                    addLabels(k.c_ref,512);
                orMap(k.c_ref, 0x40);
                k.class=992; k.c_pos=(int)(pst+6);
                MyBtreeInsertX(&k);
            }
            pst += strlen ((char *)(pst+6)) + 6+1;
        }
        //free ((void *)peNameBuff);
    }       
    // free ((void *)lpFile);
	return 1;
}       


syntax highlighted by Code2HTML, v. 0.9.1