diff --git a/rosapps/sysutils/pedump.c b/rosapps/sysutils/pedump.c new file mode 100644 index 00000000000..81a8869cece --- /dev/null +++ b/rosapps/sysutils/pedump.c @@ -0,0 +1,4308 @@ +// $Id: pedump.c,v 1.1 2001/01/13 18:19:23 ea Exp $ +// +// This program was written by Sang Cho, assistant professor at +// the department of +// computer science and engineering +// chongju university +// this program is based on the program pefile.c +// which is written by Randy Kath(Microsoft Developmer Network Technology Group) +// in june 12, 1993. +// I have investigated P.E. file format as thoroughly as possible, +// but I cannot claim that I am an expert yet, so some of its information +// may give you wrong results. +// +// +// +// language used: djgpp +// date of creation: September 28, 1997 +// +// date of first release: October 15, 1997 +// +// +// you can contact me: e-mail address: sangcho@alpha94.chongju.ac.kr +// hitel id: chokhas +// phone number: (0431) 229-8491 +82-431-229-8491 +// +// +// +// Copyright (C) 1997. by Sang Cho. +// +// Permission is granted to make and distribute verbatim copies of this +// program provided the copyright notice and this permission notice are +// preserved on all copies. +// +// +// File: pedump.c ( I included header file into source file. ) +// +// LICENSE +// Sources released under GNU General Public License version 2 +// or later by Mr. Sang Cho permission. +// +// REVISIONS +// 2000-04-23 (ea) Initial adaptation to GCC/MinGW/ROS. +// 2000-08-05 (ea) Initial raw adaptation done. +// + +#include +#include +#include +#include +#include + +#ifndef bcopy +#define bcopy(s,d,z) memcpy((d),(s),(z)) +#endif + +typedef char CHAR; +typedef short WCHAR; +typedef short SHORT; +typedef long LONG; +typedef unsigned short USHORT; +typedef unsigned long DWORD; +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef BYTE *PBYTE; +typedef WORD *PWORD; +typedef DWORD *PDWORD; +typedef void *LPVOID; +typedef int boolean; + +#define VOID void +#define BOOLEAN boolean + +#ifndef NULL +#define NULL 0 +#endif + +#define FALSE 0 +#define TRUE 1 +#define CONST const +#define LOWORD(l) ((WORD)(l)) +#define WINAPI __stdcall + +// +// Image Format +// + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_VXD_SIGNATURE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 + +typedef struct _IMAGE_DOS_HEADER + { // DOS .EXE header + + WORD e_magic; // Magic number + + WORD e_cblp; // Bytes on last page of file + + WORD e_cp; // Pages in file + + WORD e_crlc; // Relocations + + WORD e_cparhdr; // Size of header in paragraphs + + WORD e_minalloc; // Minimum extra paragraphs needed + + WORD e_maxalloc; // Maximum extra paragraphs needed + + WORD e_ss; // Initial (relative) SS value + + WORD e_sp; // Initial SP value + + WORD e_csum; // Checksum + + WORD e_ip; // Initial IP value + + WORD e_cs; // Initial (relative) CS value + + WORD e_lfarlc; // File address of relocation table + + WORD e_ovno; // Overlay number + + WORD e_res[4]; // Reserved words + + WORD e_oemid; // OEM identifier (for e_oeminfo) + + WORD e_oeminfo; // OEM information; e_oemid specific + + WORD e_res2[10]; // Reserved words + + LONG e_lfanew; // File address of new exe header + + } +IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +// +// File header format. +// + + + +typedef struct _IMAGE_FILE_HEADER + { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; + } +IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0x160 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_R10000 0x168 // MIPS little-endian +#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian + + + +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY + { + DWORD VirtualAddress; + DWORD Size; + + } +IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER + { + // + // Standard fields. + // + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + // + // NT additional fields. + // + + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; + + } +IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER; + + +typedef struct _IMAGE_NT_HEADERS + { + DWORD Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; + + } +IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS; + + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP) +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER + { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union + { + DWORD PhysicalAddress; + DWORD VirtualSize; + } + Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; + + } +IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY + { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + PDWORD *AddressOfFunctions; + PDWORD *AddressOfNames; + PWORD *AddressOfNameOrdinals; + + } +IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME + { + WORD Hint; + BYTE Name[1]; + + } +IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +#define IMAGE_ORDINAL_FLAG 0x80000000 +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + + +// +// Resource Format. +// + +// +// Resource directory consists of two counts, following by a variable length +// array of directory entries. The first count is the number of entries at +// beginning of the array that have actual names associated with each entry. +// The entries are in ascending order, case insensitive strings. The second +// count is the number of entries that immediately follow the named entries. +// This second count identifies the number of entries that have 16-bit integer +// Ids as their name. These entries are also sorted in ascending order. +// +// This structure allows fast lookup by either name or number, but for any +// given resource entry only one form of lookup is supported, not both. +// This is consistant with the syntax of the .RC file and the .RES file. +// + +// Predefined resource types ... there may be some more, but I don't have +// the information yet. .....sang cho..... + +#define RT_NEWRESOURCE 0x2000 +#define RT_ERROR 0x7fff +#define RT_CURSOR 1 +#define RT_BITMAP 2 +#define RT_ICON 3 +#define RT_MENU 4 +#define RT_DIALOG 5 +#define RT_STRING 6 +#define RT_FONTDIR 7 +#define RT_FONT 8 +#define RT_ACCELERATORS 9 +#define RT_RCDATA 10 +#define RT_MESSAGETABLE 11 +#define RT_GROUP_CURSOR 12 +#define RT_GROUP_ICON 14 +#define RT_VERSION 16 +#define NEWBITMAP (RT_BITMAP|RT_NEWRESOURCE) +#define NEWMENU (RT_MENU|RT_NEWRESOURCE) +#define NEWDIALOG (RT_DIALOG|RT_NEWRESOURCE) + + +typedef struct _IMAGE_RESOURCE_DIRECTORY + { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; +// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[1]; + + } +IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + +// +// Each directory contains the 32-bit Name of the entry and an offset, +// relative to the beginning of the resource directory of the data associated +// with this directory entry. If the name of the entry is an actual text +// string instead of an integer Id, then the high order bit of the name field +// is set to one and the low order 31-bits are an offset, relative to the +// beginning of the resource directory of the string, which is of type +// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the +// low-order 16-bits are the integer Id that identify this resource directory +// entry. If the directory entry is yet another resource directory (i.e. a +// subdirectory), then the high order bit of the offset field will be +// set to indicate this. Otherwise the high bit is clear and the offset +// field points to a resource data entry. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY + { + DWORD Name; + DWORD OffsetToData; + + } +IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +// +// For resource directory entries that have actual string names, the Name +// field of the directory entry points to an object of the following type. +// All of these string objects are stored together after the last resource +// directory entry and before the first resource data object. This minimizes +// the impact of these variable length objects on the alignment of the fixed +// size directory entry objects. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING + { + WORD Length; + CHAR NameString[1]; + + } +IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U + { + WORD Length; + WCHAR NameString[1]; + + } +IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; + + +// +// Each resource data entry describes a leaf node in the resource directory +// tree. It contains an offset, relative to the beginning of the resource +// directory of the data for the resource, a size field that gives the number +// of bytes of data at that offset, a CodePage that should be used when +// decoding code point values within the resource data. Typically for new +// applications the code page would be the unicode code page. +// + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY + { + DWORD OffsetToData; + DWORD Size; + DWORD CodePage; + DWORD Reserved; + + } +IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + + +// Menu Resources ... added by .....sang cho.... + +// Menu resources are composed of a menu header followed by a sequential list +// of menu items. There are two types of menu items: pop-ups and normal menu +// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with +// an empty name, zero ID, and zero flags. + +typedef struct _IMAGE_MENU_HEADER + { + WORD wVersion; // Currently zero + + WORD cbHeaderSize; // Also zero + + } +IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER; + +typedef struct _IMAGE_POPUP_MENU_ITEM + { + WORD fItemFlags; + WCHAR szItemText[1]; + + } +IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM; + +typedef struct _IMAGE_NORMAL_MENU_ITEM + { + WORD fItemFlags; + WORD wMenuID; + WCHAR szItemText[1]; + + } +IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM; + +#define GRAYED 0x0001 // GRAYED keyword +#define INACTIVE 0x0002 // INACTIVE keyword +#define BITMAP 0x0004 // BITMAP keyword +#define OWNERDRAW 0x0100 // OWNERDRAW keyword +#define CHECKED 0x0008 // CHECKED keyword +#define POPUP 0x0010 // used internally +#define MENUBARBREAK 0x0020 // MENUBARBREAK keyword +#define MENUBREAK 0x0040 // MENUBREAK keyword +#define ENDMENU 0x0080 // used internally + + +// Dialog Box Resources .................. added by sang cho. + +// A dialog box is contained in a single resource and has a header and +// a portion repeated for each control in the dialog box. +// The item DWORD IStyle is a standard window style composed of flags found +// in WINDOWS.H. +// The default style for a dialog box is: +// WS_POPUP | WS_BORDER | WS_SYSMENU +// +// The itme marked "Name or Ordinal" are : +// If the first word is an 0xffff, the next two bytes contain an ordinal ID. +// Otherwise, the first one or more WORDS contain a double-null-terminated string. +// An empty string is represented by a single WORD zero in the first location. +// +// The WORD wPointSize and WCHAR szFontName entries are present if the FONT +// statement was included for the dialog box. This can be detected by checking +// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these +// entries will be present. + +typedef struct _IMAGE_DIALOG_BOX_HEADER1 + { + DWORD IStyle; + DWORD IExtendedStyle; // New for Windows NT + + WORD nControls; // Number of Controls + + WORD x; + WORD y; + WORD cx; + WORD cy; +// N_OR_O MenuName; // Name or Ordinal ID + // N_OR_O ClassName; // Name or Ordinal ID + // WCHAR szCaption[]; + // WORD wPointSize; // Only here if FONT set for dialog + // WCHAR szFontName[]; // This too + } +IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER; + +typedef union _NAME_OR_ORDINAL + { // Name or Ordinal ID + + struct _ORD_ID + { + WORD flgId; + WORD Id; + } + ORD_ID; + WCHAR szName[1]; + } +NAME_OR_ORDINAL, *PNAME_OR_ORDINAL; + +// The data for each control starts on a DWORD boundary (which may require +// some padding from the previous control), and its format is as follows: + +typedef struct _IMAGE_CONTROL_DATA + { + DWORD IStyle; + DWORD IExtendedStyle; + WORD x; + WORD y; + WORD cx; + WORD cy; + WORD wId; +// N_OR_O ClassId; + // N_OR_O Text; + // WORD nExtraStuff; + } +IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA; + +#define BUTTON 0x80 +#define EDIT 0x81 +#define STATIC 0x82 +#define LISTBOX 0x83 +#define SCROLLBAR 0x84 +#define COMBOBOX 0x85 + +// The various statements used in a dialog script are all mapped to these +// classes along with certain modifying styles. The values for these styles +// can be found in WINDOWS.H. All dialog controls have the default styles +// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows: +// +// Statement Default Class Default Styles +// CONTROL None WS_CHILD|WS_VISIBLE +// LTEXT STATIC ES_LEFT +// RTEXT STATIC ES_RIGHT +// CTEXT STATIC ES_CENTER +// LISTBOX LISTBOX WS_BORDER|LBS_NOTIFY +// CHECKBOX BUTTON BS_CHECKBOX|WS_TABSTOP +// PUSHBUTTON BUTTON BS_PUSHBUTTON|WS_TABSTOP +// GROUPBOX BUTTON BS_GROUPBOX +// DEFPUSHBUTTON BUTTON BS_DFPUSHBUTTON|WS_TABSTOP +// RADIOBUTTON BUTTON BS_RADIOBUTTON +// AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX +// AUTO3STATE BUTTON BS_AUTO3STATE +// AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON +// PUSHBOX BUTTON BS_PUSHBOX +// STATE3 BUTTON BS_3STATE +// EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP +// COMBOBOX COMBOBOX None +// ICON STATIC SS_ICON +// SCROLLBAR SCROLLBAR None +/// + +#define WS_OVERLAPPED 0x00000000L +#define WS_POPUP 0x80000000L +#define WS_CHILD 0x40000000L +#define WS_CLIPSIBLINGS 0x04000000L +#define WS_CLIPCHILDREN 0x02000000L +#define WS_VISIBLE 0x10000000L +#define WS_DISABLED 0x08000000L +#define WS_MINIMIZE 0x20000000L +#define WS_MAXIMIZE 0x01000000L +#define WS_CAPTION 0x00C00000L +#define WS_BORDER 0x00800000L +#define WS_DLGFRAME 0x00400000L +#define WS_VSCROLL 0x00200000L +#define WS_HSCROLL 0x00100000L +#define WS_SYSMENU 0x00080000L +#define WS_THICKFRAME 0x00040000L +#define WS_MINIMIZEBOX 0x00020000L +#define WS_MAXIMIZEBOX 0x00010000L +#define WS_GROUP 0x00020000L +#define WS_TABSTOP 0x00010000L + +// other aliases +#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX) +#define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU) +#define WS_CHILDWINDOW (WS_CHILD) +#define WS_TILED WS_OVERLAPPED +#define WS_ICONIC WS_MINIMIZE +#define WS_SIZEBOX WS_THICKFRAME +#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW + +#define WS_EX_DLGMODALFRAME 0x00000001L +#define WS_EX_NOPARENTNOTIFY 0x00000004L +#define WS_EX_TOPMOST 0x00000008L +#define WS_EX_ACCEPTFILES 0x00000010L +#define WS_EX_TRANSPARENT 0x00000020L + +#define BS_PUSHBUTTON 0x00000000L +#define BS_DEFPUSHBUTTON 0x00000001L +#define BS_CHECKBOX 0x00000002L +#define BS_AUTOCHECKBOX 0x00000003L +#define BS_RADIOBUTTON 0x00000004L +#define BS_3STATE 0x00000005L +#define BS_AUTO3STATE 0x00000006L +#define BS_GROUPBOX 0x00000007L +#define BS_USERBUTTON 0x00000008L +#define BS_AUTORADIOBUTTON 0x00000009L +#define BS_OWNERDRAW 0x0000000BL +#define BS_LEFTTEXT 0x00000020L + +#define ES_LEFT 0x00000000L +#define ES_CENTER 0x00000001L +#define ES_RIGHT 0x00000002L +#define ES_MULTILINE 0x00000004L +#define ES_UPPERCASE 0x00000008L +#define ES_LOWERCASE 0x00000010L +#define ES_PASSWORD 0x00000020L +#define ES_AUTOVSCROLL 0x00000040L +#define ES_AUTOHSCROLL 0x00000080L +#define ES_NOHIDESEL 0x00000100L +#define ES_OEMCONVERT 0x00000400L +#define ES_READONLY 0x00000800L +#define ES_WANTRETURN 0x00001000L + +#define LBS_NOTIFY 0x0001L +#define LBS_SORT 0x0002L +#define LBS_NOREDRAW 0x0004L +#define LBS_MULTIPLESEL 0x0008L +#define LBS_OWNERDRAWFIXED 0x0010L +#define LBS_OWNERDRAWVARIABLE 0x0020L +#define LBS_HASSTRINGS 0x0040L +#define LBS_USETABSTOPS 0x0080L +#define LBS_NOINTEGRALHEIGHT 0x0100L +#define LBS_MULTICOLUMN 0x0200L +#define LBS_WANTKEYBOARDINPUT 0x0400L +#define LBS_EXTENDEDSEL 0x0800L +#define LBS_DISABLENOSCROLL 0x1000L + +#define SS_LEFT 0x00000000L +#define SS_CENTER 0x00000001L +#define SS_RIGHT 0x00000002L +#define SS_ICON 0x00000003L +#define SS_BLACKRECT 0x00000004L +#define SS_GRAYRECT 0x00000005L +#define SS_WHITERECT 0x00000006L +#define SS_BLACKFRAME 0x00000007L +#define SS_GRAYFRAME 0x00000008L +#define SS_WHITEFRAME 0x00000009L +#define SS_SIMPLE 0x0000000BL +#define SS_LEFTNOWORDWRAP 0x0000000CL +#define SS_BITMAP 0x0000000EL + +// +// Debug Format +// + +typedef struct _IMAGE_DEBUG_DIRECTORY + { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Type; + DWORD SizeOfData; + DWORD AddressOfRawData; + DWORD PointerToRawData; + } +IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 + + +typedef struct _IMAGE_DEBUG_MISC + { + DWORD DataType; // type of misc data, see defines + + DWORD Length; // total length of record, rounded to four + // byte multiple. + + BOOLEAN Unicode; // TRUE if data is unicode string + + BYTE Reserved[3]; + BYTE Data[1]; // Actual data + + } +IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC; + + +// +// Debugging information can be stripped from an image file and placed +// in a separate .DBG file, whose file name part is the same as the +// image file name part (e.g. symbols for CMD.EXE could be stripped +// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED +// flag in the Characteristics field of the file header. The beginning of +// the .DBG file contains the following structure which captures certain +// information from the image file. This allows a debug to proceed even if +// the original image file is not accessable. This header is followed by +// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more +// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in +// the image file contain file offsets relative to the beginning of the +// .DBG file. +// +// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure +// is left in the image file, but not mapped. This allows a debugger to +// compute the name of the .DBG file, from the name of the image in the +// IMAGE_DEBUG_MISC structure. +// + +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER + { + WORD Signature; + WORD Flags; + WORD Machine; + WORD Characteristics; + DWORD TimeDateStamp; + DWORD CheckSum; + DWORD ImageBase; + DWORD SizeOfImage; + DWORD NumberOfSections; + DWORD ExportedNamesSize; + DWORD DebugDirectorySize; + DWORD SectionAlignment; + DWORD Reserved[2]; + } +IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; + +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 + +#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 +#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the + // old checksum didn't match. + + +// +// End Image Format +// + + +#define SIZE_OF_NT_SIGNATURE sizeof (DWORD) +#define MAXRESOURCENAME 13 + +/* global macros to define header offsets into file */ +/* offset to PE file signature */ +#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew)) + +/* DOS header identifies the NT PEFile signature dword + the PEFILE header exists just after that dword */ +#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE)) + +/* PE optional header is immediately after PEFile header */ +#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER))) + +/* section headers are immediately after PE optional header */ +#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \ + ((PIMAGE_DOS_HEADER)a)->e_lfanew + \ + SIZE_OF_NT_SIGNATURE + \ + sizeof (IMAGE_FILE_HEADER) + \ + sizeof (IMAGE_OPTIONAL_HEADER))) + + +typedef struct tagImportDirectory + { + DWORD dwRVAFunctionNameList; + DWORD dwUseless1; + DWORD dwUseless2; + DWORD dwRVAModuleName; + DWORD dwRVAFunctionAddressList; + } +IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY; + + +/* global prototypes for functions in pefile.c */ +/* PE file header info */ +BOOL WINAPI GetDosHeader (LPVOID, PIMAGE_DOS_HEADER); +DWORD WINAPI ImageFileType (LPVOID); +BOOL WINAPI GetPEFileHeader (LPVOID, PIMAGE_FILE_HEADER); + +/* PE optional header info */ +BOOL WINAPI GetPEOptionalHeader (LPVOID, PIMAGE_OPTIONAL_HEADER); +LPVOID WINAPI GetModuleEntryPoint (LPVOID); +int WINAPI NumOfSections (LPVOID); +LPVOID WINAPI GetImageBase (LPVOID); +LPVOID WINAPI ImageDirectoryOffset (LPVOID, DWORD); +LPVOID WINAPI ImageDirectorySection (LPVOID, DWORD); + +/* PE section header info */ +//int WINAPI GetSectionNames (LPVOID, HANDLE, char **); +int WINAPI GetSectionNames (LPVOID, char **); +BOOL WINAPI GetSectionHdrByName (LPVOID, PIMAGE_SECTION_HEADER, char *); + +// +// structur to store string tokens +// +typedef struct _Str_P + { + char flag; // string_flag '@' or '%' or '#' + + char *pos; // starting postion of string + + int length; // length of string + + BOOL wasString; // if it were stringMode or not + + } +Str_P; + +/* import section info */ +int WINAPI GetImportModuleNames (LPVOID, char **); +int WINAPI GetImportFunctionNamesByModule (LPVOID, char *, char **); + +// import function name reporting +int WINAPI GetStringLength (char *); +void WINAPI GetPreviousParamString (char *, char *); +void WINAPI TranslateParameters (char **, char **, char **); +BOOL WINAPI StringExpands (char **, char **, char **, Str_P *); +LPVOID WINAPI TranslateFunctionName (char *); + +/* export section info */ +int WINAPI GetExportFunctionNames (LPVOID, char **); + +/* resource section info */ +int WINAPI GetNumberOfResources (LPVOID); +int WINAPI GetListOfResourceTypes (LPVOID, char **); +int WINAPI MenuScan (int *, WORD **); +int WINAPI MenuFill (char **, WORD **); +void WINAPI StrangeMenuFill (char **, WORD **, int); +int WINAPI GetContentsOfMenu (LPVOID, char **); +int WINAPI PrintMenu (int, char **); +int WINAPI PrintStrangeMenu (char **); +int WINAPI dumpMenu (char **psz, int size); + +/* debug section info */ +BOOL WINAPI IsDebugInfoStripped (LPVOID); +int WINAPI RetrieveModuleName (LPVOID, char **); +BOOL WINAPI IsDebugFile (LPVOID); +BOOL WINAPI GetSeparateDebugHeader (LPVOID, PIMAGE_SEPARATE_DEBUG_HEADER); + + +/********************************************************************** + * NAME + * + * DESCRIPTION + * Copy DOS header information to structure. + * + * ARGUMENTS + */ +BOOL WINAPI +GetDosHeader ( + LPVOID lpFile, + PIMAGE_DOS_HEADER pHeader +) +{ + /* + * DOS header represents first structure + * of bytes in PE image file. + */ + if ((WORD) IMAGE_DOS_SIGNATURE == *(WORD *) lpFile) + { + bcopy ( + lpFile, + (LPVOID) pHeader, + sizeof (IMAGE_DOS_HEADER) + ); + return TRUE; + } + return FALSE; +} + + + + +/* return file signature */ +DWORD WINAPI +ImageFileType ( + LPVOID lpFile) +{ + /* dos file signature comes first */ + if (*(USHORT *) lpFile == IMAGE_DOS_SIGNATURE) + { + /* determine location of PE File header from dos header */ + if (LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE || + LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE) + return (DWORD) LOWORD (*(DWORD *) NTSIGNATURE (lpFile)); + + else if (*(DWORD *) NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE) + return IMAGE_NT_SIGNATURE; + + else + return IMAGE_DOS_SIGNATURE; + } + + else + /* unknown file type */ + return 0; +} + + + + +/* copy file header information to structure */ +BOOL WINAPI +GetPEFileHeader ( + LPVOID lpFile, + PIMAGE_FILE_HEADER pHeader) +{ + /* file header follows dos header */ + if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE) + bcopy (PEFHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_FILE_HEADER)); + else + return FALSE; + + return TRUE; +} + + + + + +/* copy optional header info to structure */ +BOOL WINAPI +GetPEOptionalHeader ( + LPVOID lpFile, + PIMAGE_OPTIONAL_HEADER pHeader) +{ + /* optional header follows file header and dos header */ + if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE) + bcopy (OPTHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_OPTIONAL_HEADER)); + else + return FALSE; + + return TRUE; +} + + + + +/* function returns the entry point for an exe module lpFile must + be a memory mapped file pointer to the beginning of the image file */ +LPVOID WINAPI +GetModuleEntryPoint ( + LPVOID lpFile) +{ + PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); + + if (poh != NULL) + return (LPVOID) (poh->AddressOfEntryPoint); + else + return NULL; +} + + + + +/* return the total number of sections in the module */ +int WINAPI +NumOfSections ( + LPVOID lpFile) +{ + /* number os sections is indicated in file header */ + return ((int) ((PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile))->NumberOfSections); +} + + + + +/* retrieve entry point */ +LPVOID WINAPI +GetImageBase ( + LPVOID lpFile) +{ + PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); + + if (poh != NULL) + return (LPVOID) (poh->ImageBase); + else + return NULL; +} + + + +// +// This function is written by sang cho +// .. october 5, 1997 +// +/* function returns the actual address of given RVA, lpFile must + be a memory mapped file pointer to the beginning of the image file */ +LPVOID WINAPI +GetActualAddress ( + LPVOID lpFile, + DWORD dwRVA) +{ +// PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile); + PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); + int nSections = NumOfSections (lpFile); + int i = 0; + + if (dwRVA == NULL) + return NULL; + if (dwRVA & 0x80000000) + { + //return (LPVOID)dwRVA; + printf ("\n$$ what is going on $$"); + exit (0); + } + + /* locate section containing image directory */ + while (i++ < nSections) + { + if (psh->VirtualAddress <= (DWORD) dwRVA && + psh->VirtualAddress + psh->SizeOfRawData > (DWORD) dwRVA) + break; + psh++; + } + + if (i > nSections) + return NULL; + + /* return image import directory offset */ + return (LPVOID) (((int) lpFile + (int) dwRVA - psh->VirtualAddress) + + (int) psh->PointerToRawData); +} + + +// +// This function is modified by sang cho +// +// +/* return offset to specified IMAGE_DIRECTORY entry */ +LPVOID WINAPI +ImageDirectoryOffset ( + LPVOID lpFile, + DWORD dwIMAGE_DIRECTORY) +{ + PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); + PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); + int nSections = NumOfSections (lpFile); + int i = 0; + LPVOID VAImageDir; + + /* must be 0 thru (NumberOfRvaAndSizes-1) */ + if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes) + return NULL; + + /* locate specific image directory's relative virtual address */ + VAImageDir = (LPVOID) poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress; + + if (VAImageDir == NULL) + return NULL; + /* locate section containing image directory */ + while (i++ < nSections) + { + if (psh->VirtualAddress <= (DWORD) VAImageDir && + psh->VirtualAddress + psh->SizeOfRawData > (DWORD) VAImageDir) + break; + psh++; + } + + if (i > nSections) + return NULL; + + /* return image import directory offset */ + return (LPVOID) (((int) lpFile + (int) VAImageDir - psh->VirtualAddress) + + (int) psh->PointerToRawData); +} + + +/* function retrieve names of all the sections in the file */ +int WINAPI +GetSectionNames ( + LPVOID lpFile, + char **pszSections) +{ + int nSections = NumOfSections (lpFile); + int i, nCnt = 0; + PIMAGE_SECTION_HEADER psh; + char *ps; + + + if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE || + (psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) == NULL) + return 0; + + /* count the number of chars used in the section names */ + for (i = 0; i < nSections; i++) + nCnt += strlen (psh[i].Name) + 1; + + /* allocate space for all section names from heap */ + ps = *pszSections = (char *) calloc (nCnt, 1); + + + for (i = 0; i < nSections; i++) + { + strcpy (ps, psh[i].Name); + ps += strlen (psh[i].Name) + 1; + } + + return nCnt; +} + + + + +/* function gets the function header for a section identified by name */ +BOOL WINAPI +GetSectionHdrByName ( + LPVOID lpFile, + IMAGE_SECTION_HEADER * sh, + char *szSection) +{ + PIMAGE_SECTION_HEADER psh; + int nSections = NumOfSections (lpFile); + int i; + + + if ((psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) != NULL) + { + /* find the section by name */ + for (i = 0; i < nSections; i++) + { + if (!strcmp (psh->Name, szSection)) + { + /* copy data to header */ + bcopy ((LPVOID) psh, (LPVOID) sh, sizeof (IMAGE_SECTION_HEADER)); + return TRUE; + } + else + psh++; + } + } + return FALSE; +} + + + +// +// This function is modified by sang cho +// +// +/* get import modules names separated by null terminators, return module count */ +int WINAPI +GetImportModuleNames ( + LPVOID lpFile, + char **pszModules) +{ + PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) + ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); + // + // sometimes there may be no section for idata or edata + // instead rdata or data section may contain these sections .. + // or even module names or function names are in different section. + // so that's why we need to get actual address of RVAs each time. + // ...................sang cho.................. + // + // PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) + // ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); + // BYTE *pData = (BYTE *)pid; + // DWORD *pdw = (DWORD *)pid; + int nCnt = 0, nSize = 0, i; + char *pModule[1024]; /* hardcoded maximum number of modules?? */ + char *psz; + + if (pid == NULL) + return 0; + + // pData = (BYTE *)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); + + /* extract all import modules */ + while (pid->dwRVAModuleName) + { + /* allocate temporary buffer for absolute string offsets */ + //pModule[nCnt] = (char *)(pData + pid->dwRVAModuleName); + pModule[nCnt] = (char *) GetActualAddress (lpFile, pid->dwRVAModuleName); + nSize += strlen (pModule[nCnt]) + 1; + + /* increment to the next import directory entry */ + pid++; + nCnt++; + } + + /* copy all strings to one chunk of memory */ + *pszModules = (char *) calloc (nSize, 1); + psz = *pszModules; + for (i = 0; i < nCnt; i++) + { + strcpy (psz, pModule[i]); + psz += strlen (psz) + 1; + } + return nCnt; +} + + +// +// This function is rewritten by sang cho +// +// +/* get import module function names separated by null terminators, return function count */ +int WINAPI +GetImportFunctionNamesByModule ( + LPVOID lpFile, + char *pszModule, + char **pszFunctions) +{ + PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY) + ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); + // + // sometimes there may be no section for idata or edata + // instead rdata or data section may contain these sections .. + // or even module names or function names are in different section. + // so that's why we need to get actual address each time. + // ...................sang cho.................. + // + //PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) + //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT); + //DWORD dwBase; + int nCnt = 0, nSize = 0; + int nnid = 0; + int mnlength, i; + DWORD dwFunctionName; + DWORD dwFunctionAddress; + char name[128]; + char buff[256]; // enough for any string ?? + + char *psz; + DWORD *pdw; + + //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); + + /* find module's pid */ + while (pid->dwRVAModuleName && + strcmp (pszModule, (char *) GetActualAddress (lpFile, pid->dwRVAModuleName))) + pid++; + + /* exit if the module is not found */ + if (!pid->dwRVAModuleName) + return 0; + + // I am doing this to get rid of .dll from module name + strcpy (name, pszModule); + mnlength = strlen (pszModule); + for (i = 0; i < mnlength; i++) + if (name[i] == '.') + break; + name[i] = 0; + mnlength = i; + + /* count number of function names and length of strings */ + dwFunctionName = pid->dwRVAFunctionNameList; + + // IMAGE_IMPORT_BY_NAME OR IMAGE_THUNK_DATA + // modified by Sang Cho + while (dwFunctionName && + *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName))) + { + if ((*pdw) & 0x80000000) + nSize += mnlength + 10 + 1 + 6; + else + nSize += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1 + 6; + dwFunctionName += 4; + nCnt++; + } + + /* allocate memory for function names */ + *pszFunctions = (char *) calloc (nSize, 1); + psz = *pszFunctions; + + // + // I modified this part to store function address (4 bytes), + // ord number (2 bytes), + // and name strings (which was there originally) + // so that's why there are 6 more bytes...... +6, or +4 and +2 etc. + // these informations are used where they are needed. + // ...........sang cho.................. + // + /* copy function names to mempry pointer */ + dwFunctionName = pid->dwRVAFunctionNameList; + dwFunctionAddress = pid->dwRVAFunctionAddressList; + while (dwFunctionName && + *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName))) + { + if ((*pdw) & 0x80000000) + { + *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress)); + psz += 4; + *(short *) psz = *(short *) pdw; + psz += 2; + sprintf (buff, "%s:NoName%04d", name, nnid++); + strcpy (psz, buff); + psz += strlen (buff) + 1; + } + else + { + *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress)); + psz += 4; + *(short *) psz = (*(short *) GetActualAddress (lpFile, *pdw)); + psz += 2; + strcpy (psz, (char *) GetActualAddress (lpFile, *pdw + 2)); + psz += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1; + } + dwFunctionName += 4; + dwFunctionAddress += 4; + } + + return nCnt; +} + + + + +// +// This function is written by sang cho +// October 6, 1997 +// +/* get numerically expressed string length */ +int WINAPI +GetStringLength ( + char *psz) +{ + if (!isdigit (*psz)) + return 0; + if (isdigit (*(psz + 1))) + return (*psz - '0') * 10 + *(psz + 1) - '0'; + else + return *psz - '0'; +} + + + + +// +// This function is written by sang cho +// October 12, 1997 +// + +/* translate parameter part of condensed name */ +void WINAPI +GetPreviousParamString ( + char *xpin, // read-only source + char *xpout) // translated result + { + int n = 0; + char *pin, *pout; + + pin = xpin; + pout = xpout; + + pin--; + if (*pin == ',') + pin--; + else + { + printf ("\n **error PreviousParamString1 char = %c", *pin); + exit (0); + } + + while (*pin) + { + if (*pin == '>') + n++; + else if (*pin == '<') + n--; + else if (*pin == ')') + n++; + + if (n > 0) + { + if (*pin == '(') + n--; + } + else if (strchr (",(", *pin)) + break; + pin--; + } + + //printf("\n ----- %s", pin); + if (strchr (",(", *pin)) + { + pin++; + } // printf("\n %s", pin); } + + else + { + printf ("\n **error PreviousParamString2"); + exit (0); + } + + n = xpin - pin - 1; + strncpy (pout, pin, n); + *(pout + n) = 0; +} + + + + +// +// This function is written by sang cho +// October 10, 1997 +// + +/* translate parameter part of condensed name */ +void WINAPI +TranslateParameters ( + char **ppin, // read-only source + char **ppout, // translated result + char **pps) // parameter stack + { + int i, n; + char c; + char name[128]; + char *pin, *pout, *ps; + + //printf(" %c ", **in); + pin = *ppin; + pout = *ppout; + ps = *pps; + c = *pin; + switch (c) + { + // types processing + case 'b': + strcpy (pout, "byte"); + pout += 4; + pin++; + break; + case 'c': + strcpy (pout, "char"); + pout += 4; + pin++; + break; + case 'd': + strcpy (pout, "double"); + pout += 6; + pin++; + break; + case 'f': + strcpy (pout, "float"); + pout += 5; + pin++; + break; + case 'g': + strcpy (pout, "long double"); + pout += 11; + pin++; + break; + case 'i': + strcpy (pout, "int"); + pout += 3; + pin++; + break; + case 'l': + strcpy (pout, "long"); + pout += 4; + pin++; + break; + case 's': + strcpy (pout, "short"); + pout += 5; + pin++; + break; + case 'v': + strcpy (pout, "void"); + pout += 4; + pin++; + break; + // postfix processing + case 'M': + case 'p': + if (*(pin + 1) == 'p') + { + *ps++ = 'p'; + pin += 2; + } + else + { + *ps++ = '*'; + pin++; + } + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + case 'q': + *pout++ = '('; + pin++; + *ps++ = 'q'; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + case 'r': + if (*(pin + 1) == 'p') + { + *ps++ = 'r'; + pin += 2; + } + else + { + *ps++ = '&'; + pin++; + } + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + // repeat processing + case 't': + if (isdigit (*(pin + 1))) + { + n = *(pin + 1) - '0'; + pin++; + pin++; + GetPreviousParamString (pout, name); + strcpy (pout, name); + pout += strlen (name); + for (i = 1; i < n; i++) + { + *pout++ = ','; + strcpy (pout, name); + pout += strlen (name); + } + } + else + pin++; + break; + // prefix processing + case 'u': + strcpy (pout, "u"); + pout += 1; + pin++; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + case 'x': + strcpy (pout, "const "); + pout += 6; + pin++; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + case 'z': + strcpy (pout, "static "); + pout += 7; + pin++; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + default: + strcpy (pout, "!1!"); + pout += 3; + *pout++ = *pin++; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + } + // need to process postfix finally + c = *(ps - 1); + if (strchr ("tqx", c)) + { + if (*(pin) && !strchr ("@$%", *(pin))) + *pout++ = ','; + *ppin = pin; + *ppout = pout; + *pps = ps; + return; + } + switch (c) + { + case 'r': + strcpy (pout, "*&"); + pout += 2; + ps--; + break; + case 'p': + strcpy (pout, "**"); + pout += 2; + ps--; + break; + case '&': + strcpy (pout, "&"); + pout += 1; + ps--; + break; + case '*': + strcpy (pout, "*"); + pout += 1; + ps--; + break; + default: + strcpy (pout, "!2!"); + pout += 3; + ps--; + break; + } + if (*(pin) && !strchr ("@$%", *(pin))) + *pout++ = ','; + *ppin = pin; + *ppout = pout; + *pps = ps; +} + + +// +// This function is written by sang cho +// October 11, 1997 +// + +/* translate parameter part of condensed name */ +BOOL WINAPI +StringExpands ( + char **ppin, // read-only source + char **ppout, // translated result + char **pps, // parameter stack + Str_P * pcstr) // currently stored string + { +// int n; + // char c; + char *pin, *pout, *ps; + Str_P c_str; + BOOL stringMode = TRUE; + + pin = *ppin; + pout = *ppout; + ps = *pps; + c_str = *pcstr; + + if (strncmp (pin, "bctr", 4) == 0) + { + strncpy (pout, c_str.pos, c_str.length); + pout += c_str.length; + pin += 4; + } + else if (strncmp (pin, "bdtr", 4) == 0) + { + *pout++ = '~'; + strncpy (pout, c_str.pos, c_str.length); + pout += c_str.length; + pin += 4; + } + else if (*pin == 'o') + { + strcpy (pout, "const "); + pout += 6; + pin++; + stringMode = FALSE; + } + else if (*pin == 'q') + { + *pout++ = '('; + pin++; + *ps++ = 'q'; + stringMode = FALSE; + } + else if (*pin == 't') + { + //if (*(ps-1) == 't') { *pout++ = ','; pin++; } // this also got me... + //else october 12 .. sang + { + *pout++ = '<'; + pin++; + *ps++ = 't'; + } + stringMode = FALSE; + } + else if (strncmp (pin, "xq", 2) == 0) + { + *pout++ = '('; + pin += 2; + *ps++ = 'x'; + *ps++ = 'q'; + stringMode = FALSE; + } + else if (strncmp (pin, "bcall", 5) == 0) + { + strcpy (pout, "operator ()"); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "bsubs", 5) == 0) + { + strcpy (pout, "operator []"); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "bnwa", 4) == 0) + { + strcpy (pout, "operator new[]"); + pout += 14; + pin += 4; + } + else if (strncmp (pin, "bdla", 4) == 0) + { + strcpy (pout, "operator delete[]"); + pout += 17; + pin += 4; + } + else if (strncmp (pin, "bnew", 4) == 0) + { + strcpy (pout, "operator new"); + pout += 12; + pin += 4; + } + else if (strncmp (pin, "bdele", 5) == 0) + { + strcpy (pout, "operator delete"); + pout += 15; + pin += 5; + } + else if (strncmp (pin, "blsh", 4) == 0) + { + strcpy (pout, "operator <<"); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "brsh", 4) == 0) + { + strcpy (pout, "operator >>"); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "binc", 4) == 0) + { + strcpy (pout, "operator ++"); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "bdec", 4) == 0) + { + strcpy (pout, "operator --"); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "badd", 4) == 0) + { + strcpy (pout, "operator +"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "brplu", 5) == 0) + { + strcpy (pout, "operator +="); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "bdiv", 4) == 0) + { + strcpy (pout, "operator /"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "brdiv", 5) == 0) + { + strcpy (pout, "operator /="); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "bmul", 4) == 0) + { + strcpy (pout, "operator *"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "brmul", 5) == 0) + { + strcpy (pout, "operator *="); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "basg", 4) == 0) + { + strcpy (pout, "operator ="); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "beql", 4) == 0) + { + strcpy (pout, "operator =="); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "bneq", 4) == 0) + { + strcpy (pout, "operator !="); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "bor", 3) == 0) + { + strcpy (pout, "operator |"); + pout += 10; + pin += 3; + } + else if (strncmp (pin, "bror", 4) == 0) + { + strcpy (pout, "operator |="); + pout += 11; + pin += 4; + } + else if (strncmp (pin, "bcmp", 4) == 0) + { + strcpy (pout, "operator ~"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "bnot", 4) == 0) + { + strcpy (pout, "operator !"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "band", 4) == 0) + { + strcpy (pout, "operator &"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "brand", 5) == 0) + { + strcpy (pout, "operator &="); + pout += 11; + pin += 5; + } + else if (strncmp (pin, "bxor", 4) == 0) + { + strcpy (pout, "operator ^"); + pout += 10; + pin += 4; + } + else if (strncmp (pin, "brxor", 5) == 0) + { + strcpy (pout, "operator ^="); + pout += 11; + pin += 5; + } + else + { + strcpy (pout, "!$$$!"); + pout += 5; + } + *ppin = pin; + *ppout = pout; + *pps = ps; + return stringMode; +} // end of '$' processing + + + +//---------------------------------------------------------------------- +// structure to store string tokens +//---------------------------------------------------------------------- +//typedef struct _Str_P { +// char flag; // string_flag '@' or '%' or '#' +// char *pos; // starting postion of string +// int length; // length of string +// BOOL wasString; // if it were stringMode or not +//} Str_P; +//---------------------------------------------------------------------- +// +// I think I knocked it down finally. But who knows? +// october 12, 1997 ... sang +// +// well I have to rewrite whole part of TranslateFunctionName.. +// this time I am a little bit more experienced than 5 days ago. +// or am i??? anyway i use stacks instead of recurcive calls +// and i hope this will take care of every symptoms i have experienced.. +// october 10, 1997 .... sang +// It took a lot of time for me to figure out what is all about.... +// but still some prefixes like z (static) +// -- or some types like b (byte) ,g (long double) ,s (short) -- +// -- or postfix like M ( * ) +// -- or $or ( & ) which is pretty wierd. .. added.. october 12 +// -- also $t business is quite tricky too. (templates) +// there may be a lot of things undiscovered yet.... +// I am not so sure my interpretation is correct or not +// If I am wrong please let me know. +// october 8, 1997 .... sang +// +// +// This function is written by sang cho +// October 5, 1997 +// +/* translate condesed import function name */ +LPVOID WINAPI +TranslateFunctionName ( + char *psz) +{ + + + int i, j, n; + char c, cc; + + static char buff[512]; // result of translation + + int is = 0; + char pStack[32]; // parameter processing stack + + Str_P sStack[32]; // String processing stack + + Str_P tok; // String token + + Str_P c_str; // current string + + int iend = 0; + char *endTab[8]; // end of string position check + + char *ps; + char *pin, *pout; + BOOL stringMode = TRUE; + + if (*psz != '@') + return psz; + pin = psz; + pout = buff; + ps = pStack; + + //................................................................ + // serious users may need to run the following code. + // so I may need to include some flag options... + // If you want to know about how translation is done, + // you can just revive following line and you can see it. + // october 6, 1997 ... sang cho + //printf ("\n................................... %s", psz); // for debugging... + + //pa = pb = pout; + pin++; + tok.flag = 'A'; + tok.pos = pout; + tok.length = 0; + tok.wasString = stringMode; + sStack[is++] = tok; // initialize sStack with dummy marker + + while (*pin) + { + while (*pin) + { + c = *pin; + + //--------------------------------------------- + // check for the end of number specified string + //--------------------------------------------- + + if (iend > 0) + { + for (i = 0; i < iend; i++) + if (pin == endTab[i]) + break; + if (i < iend) + { + // move the end of endTab to ith position + endTab[i] = endTab[iend - 1]; + iend--; + + // get top of the string stack + tok = sStack[is - 1]; + + // I am expecting '#' token from stack + if (tok.flag != '#') + + { + printf ("\n**some serious error1** %c is = %d char = %c", + tok.flag, is, *pin); + exit (0); + } + + // pop '#' token I am happy now. + else + { //if (c) + //printf("\n pop # token ... current char = %c", c); + //else printf("\n pop percent token..next char = NULL"); + + is--; + } + + stringMode = tok.wasString; + + if (!stringMode) + { + // need to process postfix finally + cc = *(ps - 1); + if (strchr ("qtx", cc)) + { + if (!strchr ("@$%", c)) + *pout++ = ','; + } + else + { + switch (cc) + { + case 'r': + strcpy (pout, "*&"); + pout += 2; + ps--; + break; + case 'p': + strcpy (pout, "**"); + pout += 2; + ps--; + break; + case '&': + strcpy (pout, "&"); + pout += 1; + ps--; + break; + case '*': + strcpy (pout, "*"); + pout += 1; + ps--; + break; + default: + strcpy (pout, "!3!"); + pout += 3; + ps--; + break; + } + if (!strchr ("@$%", c)) + *pout++ = ','; + } + } + // string mode restored... + else; + } + else; // do nothing.. + + } + + //------------------------------------------------ + // special control symbol processing: + //------------------------------------------------ + + if (strchr ("@$%", c)) + break; + + //--------------------------------------------------------------- + // string part processing : no '$' met yet + // or inside of '%' block + // or inside of '#' block (numbered string) + //--------------------------------------------------------------- + + else if (stringMode) + *pout++ = *pin++; + //else if (is > 1) *pout++ = *pin++; + + //------------------------------------------------ + // parameter part processing: '$' met + //------------------------------------------------ + + else // parameter processing + + { + if (!isdigit (c)) + TranslateParameters (&pin, &pout, &ps); + else // number specified string processing + + { + n = GetStringLength (pin); + if (n < 10) + pin++; + else + pin += 2; + + // push '#' token + //if (*pin) + //printf("\n push # token .. char = %c", *pin); + //else printf("\n push percent token..next char = NULL"); + tok.flag = '#'; + tok.pos = pout; + tok.length = 0; + tok.wasString = stringMode; + sStack[is++] = tok; + + // mark end of input string + endTab[iend++] = pin + n; + stringMode = TRUE; + } + } + } // end of inner while loop + // + // beginning of new string or end of string ( quotation mark ) + // + + if (c == '%') + { + pin++; // anyway we have to proceed... + + tok = sStack[is - 1]; // get top of the sStack + + if (tok.flag == '%') + { + // pop '%' token and set c_str + //if (*pin) + //printf("\n pop percent token..next char = %c", *pin); + //else printf("\n pop percent token..next char = NULL"); + is--; + c_str = tok; + c_str.length = pout - c_str.pos; + if (*(ps - 1) == 't') + { + *pout++ = '>'; + ps--; + stringMode = tok.wasString; + } + else + { + printf ("\n**some string error3** stack = %c", *(ps - 1)); + exit (0); + } + } + else if (tok.flag == 'A' || tok.flag == '#') + { + // push '%' token + //if (*pin) + //printf("\n push percent token..next char = %c", *pin); + //else printf("\n push percent token..next char = NULL"); + tok.flag = '%'; + tok.pos = pout; + tok.length = 0; + tok.wasString = stringMode; + sStack[is++] = tok; + } + else + { + printf ("\n**some string error5**"); + exit (0); + } + } + // + // sometimes we need string to use as constructor name or destructor name + // + else if (c == '@') // get string from previous marker upto here. + + { + pin++; + tok = sStack[is - 1]; + c_str.flag = 'S'; + c_str.pos = tok.pos; + c_str.length = pout - tok.pos; + c_str.wasString = stringMode; + *pout++ = ':'; + *pout++ = ':'; + } + // + // we need to take care of parameter control sequence + // + else if (c == '$') // need to precess template or parameter part + + { + pin++; + if (stringMode) + stringMode = StringExpands (&pin, &pout, &ps, &c_str); + else + { // template parameter mode I guess "$t" + + if (is > 1) + { + if (*pin == 't') + pin++; + else + { + printf ("\nMYGOODNESS1 %c", *pin); + exit (0); + } + //ps--; + //if (*ps == 't') *pout++ = '>'; + //else { printf("\nMYGOODNESS2"); exit(0);} + *pout++ = ','; //pin++; ..this almost blowed me.... + + } + // real parameter mode I guess + // unexpected case is found ... humm what can I do... + else + { + // this is newly found twist.. it really hurts. + if (ps <= pStack) + { + if (*pin == 'q') + { + *ps++ = 'q'; + *pout++ = '('; + pin++; + } + else + { + printf ("\n** I GIVEUP ***"); + exit (0); + } + continue; + } + ps--; + while (*ps != 'q') + { + if (*ps == '*') + *pout++ = '*'; + else if (*ps == '&') + *pout++ = '&'; + else if (*ps == 'p') + { + *pout++ = '*'; + *pout++ = '*'; + } + else if (*ps == 'r') + { + *pout++ = '*'; + *pout++ = '&'; + } + else + { + printf ("\n*** SOMETHING IS WRONG1*** char= %c", *pin); + exit (0); + } + ps--; + } + *pout++ = ')'; + ps--; + while (*ps != 'q') + { + if (*ps == '*') + *pout++ = '*'; + else if (*ps == '&') + *pout++ = '&'; + else if (*ps == 'p') + { + *pout++ = '*'; + *pout++ = '*'; + } + else if (*ps == 'r') + { + *pout++ = '*'; + *pout++ = '&'; + } + else + { + printf ("\n*** SOMETHING IS WRONG2***"); + exit (0); + } + ps--; + } + ps++; + *pout++ = ','; + } + } + } // end of '$' processing + + } // end of outer while loop + // + // need to process remaining parameter stack + // + + while (ps > pStack) + { + ps--; + switch (*ps) + { + case 't': + *pout++ = '>'; + break; + case 'q': + *pout++ = ')'; + break; + case 'x': + strcpy (pout, " const"); + pout += 6; + break; + case 'r': + strcpy (pout, "*&"); + pout += 2; + break; + case 'p': + strcpy (pout, "**"); + pout += 2; + break; + case '&': + *pout++ = '&'; + break; + case '*': + *pout++ = '*'; + break; + default: + strcpy (pout, "!4!"); + pout += 3; + *pout++ = *ps; + } + } + *pout = 0; + return buff; +} + + + +// +// This function is written by sang cho +// +// +/* get exported function names separated by null terminators, return count of functions */ +int WINAPI +GetExportFunctionNames ( + LPVOID lpFile, + char **pszFunctions) +{ + //PIMAGE_SECTION_HEADER psh; + PIMAGE_EXPORT_DIRECTORY ped; + //DWORD dwBase; + DWORD imageBase; //=========================== + + char *pfns[8192] = + {NULL,}; // maximum number of functions + //============================= + + char buff[256]; // enough for any string ?? + + char *psz; //=============================== + + DWORD *pdwAddress; + DWORD *pdw1; + DWORD *pdwNames; + WORD *pwOrd; + int i, nCnt = 0, ntmp = 0; + int enid = 0, ordBase = 1; // usally ordBase is 1.... + + int enames = 0; + + /* get section header and pointer to data directory for .edata section */ + ped = (PIMAGE_EXPORT_DIRECTORY) + ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT); + + if (ped == NULL) + return 0; + + // + // sometimes there may be no section for idata or edata + // instead rdata or data section may contain these sections .. + // or even module names or function names are in different section. + // so that's why we need to get actual address each time. + // ...................sang cho.................. + // + //psh = (PIMAGE_SECTION_HEADER) + //ImageDirectorySection(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT); + + //if (psh == NULL) return 0; + + //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); + + + /* determine the offset of the export function names */ + + pdwAddress = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfFunctions); + + imageBase = (DWORD) GetImageBase (lpFile); + + ordBase = ped->Base; + + if (ped->NumberOfNames > 0) + { + pdwNames = (DWORD *) + GetActualAddress (lpFile, (DWORD) ped->AddressOfNames); + pwOrd = (WORD *) + GetActualAddress (lpFile, (DWORD) ped->AddressOfNameOrdinals); + pdw1 = pdwAddress; + + /* figure out how much memory to allocate for all strings */ + for (i = 0; i < (int) ped->NumberOfNames; i++) + { + nCnt += strlen ((char *) + GetActualAddress (lpFile, *(DWORD *) pdwNames)) + 1 + 6; + pdwNames++; + } + // get the number of unnamed functions + for (i = 0; i < (int) ped->NumberOfFunctions; i++) + if (*pdw1++) + ntmp++; + // add memory required to show unnamed functions. + if (ntmp > (int) ped->NumberOfNames) + nCnt += 18 * (ntmp - (int) ped->NumberOfNames); + + /* allocate memory for function names */ + + *pszFunctions = (char *) calloc (nCnt, 1); + pdwNames = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNames); + + /* copy string pointer to buffer */ + + for (i = 0; i < (int) ped->NumberOfNames; i++) + { + pfns[(int) (*pwOrd) + ordBase] = + (char *) GetActualAddress (lpFile, *(DWORD *) pdwNames); + pdwNames++; + pwOrd++; + } + + psz = *pszFunctions; + } + + for (i = ordBase; i < (int) ped->NumberOfFunctions + ordBase; i++) + { + if (*pdwAddress > 0) + { + *(DWORD *) psz = imageBase + *pdwAddress; + psz += 4; + *(WORD *) psz = (WORD) (i); + psz += 2; + if (pfns[i]) + { + strcpy (psz, pfns[i]); + psz += strlen (psz) + 1; + } + else + { + sprintf (buff, "ExpFn%04d()", enid++); + strcpy (psz, buff); + psz += 12; + } + enames++; + } + pdwAddress++; + } + + return enames; + +} + + +/* determine the total number of resources in the section */ +int WINAPI +GetNumberOfResources ( + LPVOID lpFile) +{ + PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType; + PIMAGE_RESOURCE_DIRECTORY_ENTRY prde; + int nCnt = 0, i; + + + /* get root directory of resource tree */ + if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset + (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) + return 0; + + /* set pointer to first resource type entry */ + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + /* loop through all resource directory entry types */ + for (i = 0; i < prdRoot->NumberOfIdEntries; i++) + { + /* locate directory or each resource type */ + prdType = (PIMAGE_RESOURCE_DIRECTORY) ((int) prdRoot + (int) prde->OffsetToData); + + /* mask off most significant bit of the data offset */ + prdType = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType ^ 0x80000000); + + /* increment count of name'd and ID'd resources in directory */ + nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries; + + /* increment to next entry */ + prde++; + } + + return nCnt; +} + + + +// +// This function is rewritten by sang cho +// +// +/* name each type of resource in the section */ +int WINAPI +GetListOfResourceTypes ( + LPVOID lpFile, + char **pszResTypes) +{ + PIMAGE_RESOURCE_DIRECTORY prdRoot; + PIMAGE_RESOURCE_DIRECTORY_ENTRY prde; + char *pMem; + char buff[32]; + int nCnt, i; + DWORD prdeName; + + + /* get root directory of resource tree */ + if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset + (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) + return 0; + + /* allocate enuff space to cover all types */ + nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1); + *pszResTypes = (char *) calloc (nCnt, 1); + if ((pMem = *pszResTypes) == NULL) + return 0; + + /* set pointer to first resource type entry */ + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + /* loop through all resource directory entry types */ + for (i = 0; i < prdRoot->NumberOfIdEntries; i++) + { + prdeName = prde->Name; + + //if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME)) + // pMem += strlen (pMem) + 1; + // + // modified by ...................................Sang Cho.. + // I can't user M/S provied funcitons here so I have to figure out + // how to do above functions. But I can settle down with the following + // code, which works pretty good for me. + // + if (prdeName == 1) + { + strcpy (pMem, "RT_CURSOR"); + pMem += 10; + } + else if (prdeName == 2) + { + strcpy (pMem, "RT_BITMAP"); + pMem += 10; + } + else if (prdeName == 3) + { + strcpy (pMem, "RT_ICON "); + pMem += 10; + } + else if (prdeName == 4) + { + strcpy (pMem, "RT_MENU "); + pMem += 10; + } + else if (prdeName == 5) + { + strcpy (pMem, "RT_DIALOG"); + pMem += 10; + } + else if (prdeName == 6) + { + strcpy (pMem, "RT_STRING"); + pMem += 10; + } + else if (prdeName == 7) + { + strcpy (pMem, "RT_FONTDIR"); + pMem += 11; + } + else if (prdeName == 8) + { + strcpy (pMem, "RT_FONT "); + pMem += 10; + } + else if (prdeName == 9) + { + strcpy (pMem, "RT_ACCELERATORS"); + pMem += 16; + } + else if (prdeName == 10) + { + strcpy (pMem, "RT_RCDATA"); + pMem += 10; + } + else if (prdeName == 11) + { + strcpy (pMem, "RT_MESSAGETABLE"); + pMem += 16; + } + else if (prdeName == 12) + { + strcpy (pMem, "RT_GROUP_CURSOR"); + pMem += 16; + } + else if (prdeName == 14) + { + strcpy (pMem, "RT_GROUP_ICON "); + pMem += 16; + } + else if (prdeName == 16) + { + strcpy (pMem, "RT_VERSION"); + pMem += 11; + } + else if (prdeName == 17) + { + strcpy (pMem, "RT_DLGINCLUDE "); + pMem += 16; + } + else if (prdeName == 19) + { + strcpy (pMem, "RT_PLUGPLAY "); + pMem += 16; + } + else if (prdeName == 20) + { + strcpy (pMem, "RT_VXD "); + pMem += 10; + } + else if (prdeName == 21) + { + strcpy (pMem, "RT_ANICURSOR "); + pMem += 16; + } + else if (prdeName == 22) + { + strcpy (pMem, "RT_ANIICON"); + pMem += 11; + } + else if (prdeName == 0x2002) + { + strcpy (pMem, "RT_NEWBITMAP"); + pMem += 13; + } + else if (prdeName == 0x2004) + { + strcpy (pMem, "RT_NEWMENU"); + pMem += 11; + } + else if (prdeName == 0x2005) + { + strcpy (pMem, "RT_NEWDIALOG"); + pMem += 13; + } + else if (prdeName == 0x7fff) + { + strcpy (pMem, "RT_ERROR "); + pMem += 10; + } + else + { + sprintf (buff, "RT_UNKNOWN:%08X", prdeName); + strcpy (pMem, buff); + pMem += 20; + } + prde++; + } + + return prdRoot->NumberOfIdEntries; +} + + + +// +// This function is written by sang cho +// October 12, 1997 +// +/* copy menu information */ +void WINAPI +StrangeMenuFill ( + char **psz, // results + WORD ** pMenu, // read-only + int size) +{ + WORD *pwd; + WORD *ptr, *pmax; + + pwd = *pMenu; + pmax = (WORD *) ((DWORD) pwd + size); + ptr = (WORD *) (*psz); + + while (pwd < pmax) + { + *ptr++ = *pwd++; + } + *psz = (char *) ptr; + *pMenu = pwd; +} + + + +// +// This function is written by sang cho +// October 1, 1997 +// +/* obtain menu information */ +int WINAPI +MenuScan ( + int *len, + WORD ** pMenu) +{ + int num = 0; + int ndetails; + WORD *pwd; + WORD flag, flag1; + WORD id, ispopup; + + + pwd = *pMenu; + + flag = *pwd; // so difficult to correctly code this so let's try this + + pwd++; + (*len) += 2; // flag store + + if ((flag & 0x0010) == 0) + { + ispopup = flag; + id = *pwd; + pwd++; + (*len) += 2; // id store + + } + else + { + ispopup = flag; + } + + while (*pwd) + { + (*len)++; + pwd++; + } + (*len)++; // name and null character + + pwd++; // skip double null + + if ((flag & 0x0010) == 0) // normal node: done + + { + *pMenu = pwd; + return (int) flag; + } + // popup node: need to go on... + while (1) + { + *pMenu = pwd; + flag1 = (WORD) MenuScan (len, pMenu); + pwd = *pMenu; + if (flag1 & 0x0080) + break; + } +// fill # of details to num above + //(*len) += 2; + *pMenu = pwd; + return flag; +} + + +// +// This function is written by sang cho +// October 2, 1997 +// +/* copy menu information */ +int WINAPI +MenuFill ( + char **psz, + WORD ** pMenu) +{ + int num = 0; + int ndetails; + char *ptr, *pTemp; + WORD *pwd; + WORD flag, flag1; + WORD id, ispopup; + + ptr = *psz; + pwd = *pMenu; + //flag = (*(PIMAGE_POPUP_MENU_ITEM *)pwd)->fItemFlags; + flag = *pwd; // so difficult to correctly code this so let's try this + + pwd++; + if ((flag & 0x0010) == 0) + { + *(WORD *) ptr = flag; // flag store + + ptr += 2; + *(WORD *) ptr = id = *pwd; // id store + + ptr += 2; + pwd++; + } + else + { + *(WORD *) ptr = flag; // flag store + + ptr += 2; + } + + while (*pwd) // name extract + + { + *ptr = *(char *) pwd; + ptr++; + pwd++; + } //name and null character + + *ptr = 0; + ptr++; + pwd++; // skip double null + + if ((flag & 0x0010) == 0) // normal node: done + + { + *pMenu = pwd; + *psz = ptr; + return (int) flag; + } + //pTemp = ptr; + //ptr += 2; + // popup node: need to go on... + while (1) + { + //num++; + *pMenu = pwd; + *psz = ptr; + flag1 = (WORD) MenuFill (psz, pMenu); + pwd = *pMenu; + ptr = *psz; + if (flag1 & 0x0080) + break; + } +// fill # of details to num above + //*(WORD *)pTemp = (WORD)num; + *pMenu = pwd; + *psz = ptr; + return flag; +} + + +// +//============================================================================== +// The following program is based on preorder-tree-traversal. +// once you understand how to traverse..... +// the rest is pretty straight forward. +// still we need to scan it first and fill it next time. +// and finally we can print it. +// +// This function is written by sang cho +// September 29, 1997 +// revised october 2, 1997 +// revised october 12, 1997 +// .............................................................................. +// ------------------------------------------------------------------------------ +// I use same structure - which is used in P.E. programs - for my reporting. +// So, my structure is as follows: +// # of menu name is stored else where ( in directory I suppose ) +// supermenuname null terminated string, only ascii is considered. +// flag tells : node is a leaf or a internal node. +// popupname null terminated string +// +// flag normal menu flag (leaf node) +// id normal menu id +// name normal menu name +// or or +// flag popup menu flag (internal node) +// popupname popup menu name +// +// flag it may folows +// id normal menu id +// name normal menu name +// or or +// flag popup menu +// popupname popup menu name +// ......... +// it goes on like this, +// but usually, it only goes a few steps,... +// ------------------------------------------------------------------------------ +/* scan menu and copy menu */ +int WINAPI +GetContentsOfMenu ( + LPVOID lpFile, + char **pszResTypes) +{ + PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage; + PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1; + PIMAGE_RESOURCE_DIR_STRING_U pMenuName; + PIMAGE_RESOURCE_DATA_ENTRY prData; + //PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) + //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE); + PIMAGE_MENU_HEADER pMenuHeader; + PIMAGE_POPUP_MENU_ITEM pPopup; + PIMAGE_NORMAL_MENU_ITEM pNormal; + char buff[32]; + int nCnt = 0, i, j; + int num = 0; + int size; + int sLength, nMenus; + WORD flag; + WORD *pwd; + DWORD prdeName; + //DWORD dwBase; obsolete + char *pMem, *pTemp; + BOOL isStrange = FALSE; + + + /* get root directory of resource tree */ + if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset + (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) + return 0; + + /* set pointer to first resource type entry */ + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + for (i = 0; i < prdType->NumberOfIdEntries; i++) + { + if (prde->Name == RT_MENU) + break; + prde++; + } + if (prde->Name != RT_MENU) + return 0; + + prdName = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdName == NULL) + return 0; + + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + // sometimes previous code tells you lots of things hidden underneath + // I wish I could save all the revisions I made ... but again .... sigh. + // october 12, 1997 sang + //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress); + + nMenus = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries; + sLength = 0; + + for (i = 0; i < prdName->NumberOfNamedEntries; i++) + { + pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U) + ((DWORD) prdType + (prde->Name ^ 0x80000000)); + sLength += pMenuName->Length + 1; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + pMenuHeader = (PIMAGE_MENU_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + + // + // normally wVersion and cbHeaderSize should be zero + // but if it is not then nothing is known to us... + // so let's do our best ... namely guessing .... and trying .... + // ... and suffering ... + // it gave me many sleepless (not exactly but I like to say this) nights. + // + + // strange case + if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) + { + //isStrange = TRUE; + pwd = (WORD *) ((DWORD) pMenuHeader + 16); + size = prData->Size; + // expect to return the length needed to report. + // sixteen more bytes to do something + sLength += 16 + size; + //StrangeMenuScan (&sLength, &pwd, size); + } + // normal case + else + { + pPopup = (PIMAGE_POPUP_MENU_ITEM) + ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); + while (1) + { + flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup)); + if (flag & 0x0080) + break; + } + } + prde++; + } + for (i = 0; i < prdName->NumberOfIdEntries; i++) + { + sLength += 12; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + pMenuHeader = (PIMAGE_MENU_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + // strange case + if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) + { + pwd = (WORD *) ((DWORD) pMenuHeader + 16); + size = prData->Size; + // expect to return the length needed to report. + // sixteen more bytes to do something + sLength += 16 + size; + //StrangeMenuScan (&sLength, &pwd, size); + } + // normal case + else + { + pPopup = (PIMAGE_POPUP_MENU_ITEM) + ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); + while (1) + { + flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup)); + if (flag & 0x0080) + break; + } + } + prde++; + } + // + // allocate memory for menu names + // + *pszResTypes = (char *) calloc (sLength, 1); + + pMem = *pszResTypes; + // + // and start all over again + // + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + for (i = 0; i < prdName->NumberOfNamedEntries; i++) + { + pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U) + ((DWORD) prdType + (prde->Name ^ 0x80000000)); + + + for (j = 0; j < pMenuName->Length; j++) + *pMem++ = (char) (pMenuName->NameString[j]); + *pMem = 0; + pMem++; + + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + pMenuHeader = (PIMAGE_MENU_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + // strange case + if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) + { + pwd = (WORD *) ((DWORD) pMenuHeader); + size = prData->Size; + strcpy (pMem, ":::::::::::"); + pMem += 12; + *(int *) pMem = size; + pMem += 4; + StrangeMenuFill (&pMem, &pwd, size); + } + // normal case + else + { + pPopup = (PIMAGE_POPUP_MENU_ITEM) + ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); + while (1) + { + flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup)); + if (flag & 0x0080) + break; + } + } + prde++; + } + for (i = 0; i < prdName->NumberOfIdEntries; i++) + { + + sprintf (buff, "MenuId_%04X", (prde->Name)); + strcpy (pMem, buff); + pMem += strlen (buff) + 1; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + pMenuHeader = (PIMAGE_MENU_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + // strange case + if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize) + { + pwd = (WORD *) ((DWORD) pMenuHeader); + size = prData->Size; + strcpy (pMem, ":::::::::::"); + pMem += 12; + *(int *) pMem = size; + pMem += 4; + StrangeMenuFill (&pMem, &pwd, size); + } + // normal case + else + { + pPopup = (PIMAGE_POPUP_MENU_ITEM) + ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER)); + while (1) + { + flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup)); + if (flag & 0x0080) + break; + } + } + prde++; + } + + return nMenus; +} + + +// +// This function is written by sang cho +// October 12, 1997 +// +/* print contents of menu */ +int WINAPI +PrintStrangeMenu ( + char **psz) +{ + + int i, j, k, l; + int num; + WORD flag1, flag2; + char buff[128]; + char *ptr, *pmax; + + //return dumpMenu (psz, size); + + ptr = *psz; + + if (strncmp (ptr, ":::::::::::", 11) != 0) + { + printf ("\n#### I don't know why!!!"); + dumpMenu (psz, 1024); + exit (0); + } + + ptr += 12; + num = *(int *) ptr; + ptr += 4; + pmax = ptr + num; + + *psz = ptr; + return dumpMenu (psz, num); + + // I will write some code later... + +} + + + + +// +// This function is written by sang cho +// October 2, 1997 +// +/* print contents of menu */ +int WINAPI +PrintMenu ( + int indent, + char **psz) +{ + + int /*i, */ j, k, l; + WORD id /*, num */ ; + WORD flag; + char buff[128]; + char *ptr; + + + ptr = *psz; + //num = *(WORD *)ptr; + //ptr += 2; + while (1) + { + flag = *(WORD *) ptr; + if (flag & 0x0010) // flag == popup + + { + printf ("\n\n"); + for (j = 0; j < indent; j++) + printf (" "); + ptr += 2; + printf ("%s {Popup}\n", ptr); + ptr += strlen (ptr) + 1; + *psz = ptr; + PrintMenu (indent + 5, psz); + ptr = *psz; + } + else // ispopup == 0 + + { + printf ("\n"); + for (j = 0; j < indent; j++) + printf (" "); + ptr += 2; + id = *(WORD *) ptr; + ptr += 2; + strcpy (buff, ptr); + l = strlen (ptr); + ptr += l + 1; + if (strchr (buff, 0x09) != NULL) + { + for (k = 0; k < l; k++) + if (buff[k] == 0x09) + break; + for (j = 0; j < l - k; j++) + buff[31 - j] = buff[l - j]; + for (j = k; j < 32 + k - l; j++) + buff[j] = 32; + } + if (strchr (buff, 0x08) != NULL) + { + for (k = 0; k < l; k++) + if (buff[k] == 0x08) + break; + for (j = 0; j < l - k; j++) + buff[31 - j] = buff[l - j]; + for (j = k; j < 32 + k - l; j++) + buff[j] = 32; + } + printf ("%s", buff); + l = strlen (buff); + for (j = l; j < 32; j++) + printf (" "); + printf ("[ID=%04Xh]", id); + *psz = ptr; + } + if (flag & 0x0080) + break; + } + return 0; +} + + +// +// This function is written by sang cho +// October 2, 1997 +// +/* the format of menu is not known so I'll do my best */ +int WINAPI +dumpMenu ( + char **psz, + int size) +{ + + int i, j, k, n, l, c; + char buff[32]; + char *ptr, *pmax; + + ptr = *psz; + pmax = ptr + size; + for (i = 0; i < (size / 16) + 1; i++) + { + n = 0; + for (j = 0; j < 16; j++) + { + c = (int) (*ptr); + if (c < 0) + c += 256; + buff[j] = c; + printf ("%02X", c); + ptr++; + if (ptr >= pmax) + break; + n++; + if (n % 4 == 0) + printf (" "); + } + n++; + if (n % 4 == 0) + printf (" "); + l = j; + j++; + for (; j < 16; j++) + { + n++; + if (n % 4 == 0) + printf (" "); + else + printf (" "); + } + printf (" "); + for (k = 0; k < l; k++) + if (isprint (c = buff[k])) + printf ("%c", c); + else + printf ("."); + printf ("\n"); + if (ptr >= pmax) + break; + } + + *psz = ptr; + return 0; +} + + + + +// +// This function is written by sang cho +// October 13, 1997 +// +/* scan dialog box and copy dialog box */ +int WINAPI +GetContentsOfDialog ( + LPVOID lpFile, + char **pszResTypes) +{ + PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage; + PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1; + PIMAGE_RESOURCE_DIR_STRING_U pDialogName; + PIMAGE_RESOURCE_DATA_ENTRY prData; + PIMAGE_DIALOG_HEADER pDialogHeader; + PIMAGE_CONTROL_DATA pControlData; + char buff[32]; + int nCnt = 0, i, j; + int num = 0; + int size; + int sLength, nDialogs; + WORD flag; + WORD *pwd; + DWORD prdeName; + char *pMem, *pTemp; + BOOL isStrange = FALSE; + + + /* get root directory of resource tree */ + if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset + (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL) + return 0; + + /* set pointer to first resource type entry */ + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + for (i = 0; i < prdType->NumberOfIdEntries; i++) + { + if (prde->Name == RT_DIALOG) + break; + prde++; + } + if (prde->Name != RT_DIALOG) + return 0; + + prdName = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdName == NULL) + return 0; + + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + + nDialogs = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries; + sLength = 0; + + for (i = 0; i < prdName->NumberOfNamedEntries; i++) + { + pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U) + ((DWORD) prdType + (prde->Name ^ 0x80000000)); + sLength += pDialogName->Length + 1; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + size = prData->Size; + sLength += 4 + size; + prde++; + } + for (i = 0; i < prdName->NumberOfIdEntries; i++) + { + sLength += 14; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + size = prData->Size; + sLength += 4 + size; + prde++; + } + // + // allocate memory for menu names + // + *pszResTypes = (char *) calloc (sLength, 1); + + pMem = *pszResTypes; + // + // and start all over again + // + prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + for (i = 0; i < prdName->NumberOfNamedEntries; i++) + { + pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U) + ((DWORD) prdType + (prde->Name ^ 0x80000000)); + + + for (j = 0; j < pDialogName->Length; j++) + *pMem++ = (char) (pDialogName->NameString[j]); + *pMem = 0; + pMem++; + + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + continue; + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + continue; + + pDialogHeader = (PIMAGE_DIALOG_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + + + + pwd = (WORD *) ((DWORD) pDialogHeader); + size = prData->Size; + *(int *) pMem = size; + pMem += 4; + StrangeMenuFill (&pMem, &pwd, size); + + prde++; + } + for (i = 0; i < prdName->NumberOfIdEntries; i++) + { + + sprintf (buff, "DialogId_%04X", (prde->Name)); + strcpy (pMem, buff); + pMem += strlen (buff) + 1; + + prdLanguage = (PIMAGE_RESOURCE_DIRECTORY) + ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000)); + if (prdLanguage == NULL) + { + printf ("\nprdLanguage = NULL"); + exit (0); + } + + prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) + ((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY)); + + prData = (PIMAGE_RESOURCE_DATA_ENTRY) + ((DWORD) prdType + prde1->OffsetToData); + if (prData == NULL) + { + printf ("\nprData = NULL"); + exit (0); + } + + pDialogHeader = (PIMAGE_DIALOG_HEADER) + GetActualAddress (lpFile, prData->OffsetToData); + + + pwd = (WORD *) ((DWORD) pDialogHeader); + size = prData->Size; + *(int *) pMem = size; + pMem += 4; + StrangeMenuFill (&pMem, &pwd, size); + + prde++; + } + + return nDialogs; +} + + +// +// This function is written by sang cho +// October 14, 1997 +// +/* print contents of dialog */ +int WINAPI +PrintNameOrOrdinal ( + char **psz) +{ + char *ptr; + + ptr = *psz; + if (*(WORD *) ptr == 0xFFFF) + { + ptr += 2; + printf ("%04X", *(WORD *) ptr); + ptr += 2; + } + else + { + printf ("%c", '"'); + while (*(WORD *) ptr) + { + printf ("%c", *ptr); + ptr += 2; + } + ptr += 2; + printf ("%c", '"'); + } + *psz = ptr; +} + + +// +// This function is written by sang cho +// October 14, 1997 +// +/* print contents of dialog */ +int WINAPI +PrintDialog ( + char **psz) +{ + int i, j, k, l, n, c; + int num, size; + DWORD flag; + WORD class; + char buff[32]; + char *ptr, *pmax; + BOOL isStrange = FALSE; + + ptr = *psz; + size = *(int *) ptr; + ptr += 4; + pmax = ptr + size; + + // IStype of Dialog Header + flag = *(DWORD *) ptr; + // + // check if flag is right or not + // it has been observed that some dialog information is strange + // and extra work is needed to fix that ... so let's try something + // + + if ((flag & 0xFFFF0000) == 0xFFFF0000) + { + flag = *(DWORD *) (ptr + 12); + num = *(short *) (ptr + 16); + isStrange = TRUE; + ptr += 26; + } + else + { + num = *(short *) (ptr + 8); + ptr += 18; + } + printf (", # of Controls=%03d, Caption:%c", num, '"'); + + // Menu name + if (*(WORD *) ptr == 0xFFFF) + ptr += 4; // ordinal + + else + { + while (*(WORD *) ptr) + ptr += 2; + ptr += 2; + } // name + + // Class name + if (*(WORD *) ptr == 0xFFFF) + ptr += 4; // ordinal + + else + { + while (*(WORD *) ptr) + ptr += 2; + ptr += 2; + } // name + + // Caption + while (*(WORD *) ptr) + { + printf ("%c", *ptr); + ptr += 2; + } + ptr += 2; + printf ("%c", '"'); + + // FONT present + if (flag & 0x00000040) + { + if (isStrange) + ptr += 6; + else + ptr += 2; // FONT size + + while (*(WORD *) ptr) + ptr += 2; // WCHARs + + ptr += 2; // double null + + } + + // strange case adjust + if (isStrange) + ptr += 8; + + // DWORD padding + if ((ptr - *psz) % 4) + ptr += 4 - ((ptr - *psz) % 4); + + // start reporting .. finally + for (i = 0; i < num; i++) + { + flag = *(DWORD *) ptr; + if (isStrange) + ptr += 14; + else + ptr += 16; + printf ("\n Control::%03d - ID:", i + 1); + + // Control ID + printf ("%04X, Class:", *(WORD *) ptr); + ptr += 2; + + // Control Class + if (*(WORD *) ptr == 0xFFFF) + { + ptr += 2; + class = *(WORD *) ptr; + ptr += 2; + switch (class) + { + case 0x80: + printf ("BUTTON "); + break; + case 0x81: + printf ("EDIT "); + break; + case 0x82: + printf ("STATIC "); + break; + case 0x83: + printf ("LISTBOX "); + break; + case 0x84: + printf ("SCROLLBAR"); + break; + case 0x85: + printf ("COMBOBOX "); + break; + default: + printf ("%04X ", class); + break; + } + } + else + PrintNameOrOrdinal (&ptr); + + printf (" Text:"); + + // Text + PrintNameOrOrdinal (&ptr); + + // nExtraStuff + ptr += 2; + + // strange case adjust + if (isStrange) + ptr += 8; + + // DWORD padding + if ((ptr - *psz) % 4) + ptr += 4 - ((ptr - *psz) % 4); + } + + /* + ptr = *psz; + printf("\n"); + + for (i=0; i<(size/16)+1; i++) + { + n = 0; + for (j=0; j<16; j++) + { + c = (int)(*ptr); + if (c<0) c+=256; + buff[j] = c; + printf ("%02X",c); + ptr++; + if (ptr >= pmax) break; + n++; + if (n%4 == 0) printf (" "); + } + n++; if (n%4 == 0) printf (" "); + l = j; + j++; + for (; j<16; j++) + { n++; if (n%4 == 0) printf (" "); else printf (" "); } + printf (" "); + for (k=0; k= pmax) break; + } + */ + + *psz = pmax; + +} + + + + + + +/* function indicates whether debug info has been stripped from file */ +BOOL WINAPI +IsDebugInfoStripped ( + LPVOID lpFile) +{ + PIMAGE_FILE_HEADER pfh; + + pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile); + + return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED); +} + + + + +/* retrieve the module name from the debug misc. structure */ +int WINAPI +RetrieveModuleName ( + LPVOID lpFile, + char **pszModule) +{ + + PIMAGE_DEBUG_DIRECTORY pdd; + PIMAGE_DEBUG_MISC pdm = NULL; + int nCnt; + + if (!(pdd = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG))) + return 0; + + while (pdd->SizeOfData) + { + if (pdd->Type == IMAGE_DEBUG_TYPE_MISC) + { + pdm = (PIMAGE_DEBUG_MISC) ((DWORD) pdd->PointerToRawData + (DWORD) lpFile); + *pszModule = (char *) calloc ((nCnt = (strlen (pdm->Data))) + 1, 1); + // may need some unicode business here...above + bcopy (pdm->Data, *pszModule, nCnt); + + break; + } + + pdd++; + } + + if (pdm != NULL) + return nCnt; + else + return 0; +} + + + + + +/* determine if this is a valid debug file */ +BOOL WINAPI +IsDebugFile ( + LPVOID lpFile) +{ + PIMAGE_SEPARATE_DEBUG_HEADER psdh; + + psdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile; + + return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE); +} + + + + +/* copy separate debug header structure from debug file */ +BOOL WINAPI +GetSeparateDebugHeader ( + LPVOID lpFile, + PIMAGE_SEPARATE_DEBUG_HEADER psdh) +{ + PIMAGE_SEPARATE_DEBUG_HEADER pdh; + + pdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile; + + if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) + { + bcopy ((LPVOID) pdh, (LPVOID) psdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER)); + return TRUE; + } + + return FALSE; +} + +// +// I tried to immitate the output of w32dasm disassembler. +// which is a pretty good program. +// but I am disappointed with this program and I myself +// am writting a disassembler. +// This PEdump program is a byproduct of that project. +// so enjoy this program and I hope we will have a little more +// knowledge on windows programming world. +// .... sang cho + +#define MAXSECTIONNUMBER 16 +#define MAXNAMESTRNUMBER 40 +int +main ( + int argc, + char **argv +) +{ + DWORD fileType; + LPVOID lpFile; + FILE *my_fp; + IMAGE_DOS_HEADER dosHdr; + PIMAGE_FILE_HEADER pfh; + PIMAGE_OPTIONAL_HEADER poh; + PIMAGE_SECTION_HEADER psh; + IMAGE_SECTION_HEADER idsh; + IMAGE_SECTION_HEADER shdr[MAXSECTIONNUMBER]; + PIMAGE_IMPORT_MODULE_DIRECTORY pid; + + int nSections; // number of sections + + int nResources; // number of resources + + int nMenus; // number of menus + + int nDialogs; // number of dialogs + + int nImportedModules; // number of imported modules + + int nFunctions; // number of functions in the imported module + + int nExportedFunctions; // number of exported funcions + + int imageBase; + int entryPoint; + + int i, j, k, n; + int mnsize; + int nCnt; + int nSize; + int fsize; + char *pnstr; + char *pst; + char *piNameBuff; // import module name buffer + + char *pfNameBuff; // import functions in the module name buffer + + char *peNameBuff; // export function name buffer + + char *pmNameBuff; // menu name buffer + + char *pdNameBuff; // dialog name buffer + + /* + * Check user arguments. + */ + if (2 == argc) + { + my_fp = fopen (argv[1], "rb"); + if (my_fp == NULL) + { + printf ( + "%s: can not open input file \"%s\".\n", + argv[0], + argv[1] + ); + exit (0); + } + } + else + { + printf ( + "%s - PE/COFF file dumper\n" + "Copyright (c) 1993 Randy Kath (MSDN Technology Group)\n" + "Copyright (c) 1997 Sang Cho (CS & Engineering - Chongju University)\n" + "Copyright (c) 2000 Emanuele Aliberti (ReactOS Development Team)\n\n", + argv[0] + ); + printf ( + "usage: %s input_file_name\n", + argv[0] + ); + exit (0); + } + /* + * Get input file's size. + */ + /* argv [0], */ + fseek (my_fp, 0L, SEEK_END); + fsize = ftell (my_fp); + rewind (my_fp); + /* + * Buffer the file in memory. + */ + lpFile = (void *) calloc (fsize, 1); + if (lpFile == NULL) + { + printf ( + "%s: can not allocate memory.\n", + argv[0] + ); + exit (0); + } + /* + * --- Start of report --- + */ + printf ("\n\nDump of file: %s\n\n", argv[1]); + + n = fread (lpFile, fsize, 1, my_fp); + + if (n == -1) + { + printf ( + "%s: failed to read the file \"%s\".\n", + argv[0], + argv[1] + ); + exit (0); + } + + GetDosHeader (lpFile, &dosHdr); + + if ((WORD) IMAGE_DOS_SIGNATURE == dosHdr.e_magic) + { + if ((dosHdr.e_lfanew > 4096) + || (dosHdr.e_lfanew < 64) + ) + { + printf ( + "%s: This file is not in PE format; it looks like in DOS format.\n", + argv[0] + ); + exit (0); + } + } + else + { + printf ( + "%s: This doesn't look like an executable file (magic = 0x%04x).\n", + argv[0], + dosHdr.e_magic + ); + exit (0); + } + + fileType = ImageFileType (lpFile); + + if (fileType != IMAGE_NT_SIGNATURE) + { + printf ( + "%s: This file is not in PE format (magic = 0x%08x).\n", + argv[0], + fileType + ); + exit (0); + } + + //===================================== + // now we can really start processing + //===================================== + + pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile); + + poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile); + + psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile); + + nSections = pfh->NumberOfSections; + + imageBase = poh->ImageBase; + + entryPoint = poh->AddressOfEntryPoint; + + if (psh == NULL) + return 0; + + /* store section headers */ + + for (i = 0; + i < nSections; + i++ + ) + { + shdr[i] = *psh++; + } + /* + * Get Code offset and size, + * Data offset and size. + */ + for (i = 0; + i < nSections; + i++ + ) + { + if (poh->BaseOfCode == shdr[i].VirtualAddress) + { + printf ( + "Code Offset = %08X, Code Size = %08X \n", + shdr[i].PointerToRawData, + shdr[i].SizeOfRawData + ); + } + if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040) + { + printf ( + "Data Offset = %08X, Data Size = %08X \n", + shdr[i].PointerToRawData, + shdr[i].SizeOfRawData + ); + break; + } + } + + printf ("\n"); + + printf ( + "Number of Objects = %04d (dec), Imagebase = %08Xh \n", + nSections, + imageBase + ); + /* + * Object name alignment. + */ + for (i = 0; + i < nSections; + i++ + ) + { + for (j = 0; + j < 7; + j++ + ) + { + if (shdr[i].Name[j] == 0) + { + shdr[i].Name[j] = 32; + } + } + shdr[i].Name[7] = 0; + } + for (i = 0; i < nSections; i++) + printf ("\n Object%02d: %8s RVA: %08X Offset: %08X Size: %08X Flags: %08X ", + i + 1, shdr[i].Name, shdr[i].VirtualAddress, shdr[i].PointerToRawData, + shdr[i].SizeOfRawData, shdr[i].Characteristics); + /* + * Get List of Resources. + */ + nResources = GetListOfResourceTypes (lpFile, &pnstr); + pst = pnstr; + printf ("\n"); + printf ("\n+++++++++++++++++++ RESOURCE INFORMATION +++++++++++++++++++"); + printf ("\n"); + if (nResources == 0) + printf ("\n There are no Resources in This Application.\n"); + else + { + printf ("\nNumber of Resource Types = %4d (decimal)\n", nResources); + for (i = 0; i < nResources; i++) + { + printf ("\n Resource Type %03d: %s", i + 1, pst); + pst += strlen ((char *) (pst)) + 1; + } + free ((void *) pnstr); + + printf ("\n"); + printf ("\n+++++++++++++++++++ MENU INFORMATION +++++++++++++++++++"); + printf ("\n"); + + nMenus = GetContentsOfMenu (lpFile, &pmNameBuff); + + if (nMenus == 0) + { + printf ("\n There are no Menus in This Application.\n"); + } + else + { + pst = pmNameBuff; + printf ("\nNumber of Menus = %4d (decimal)", nMenus); + + //dumpMenu(&pst, 8096); + for (i = 0; i < nMenus; i++) + { + // menu ID print + printf ("\n\n%s", pst); + pst += strlen (pst) + 1; + printf ("\n-------------"); + if (strncmp (pst, ":::::::::::", 11) == 0) + { + printf ("\n"); + PrintStrangeMenu (&pst); + } + else + { + PrintMenu (6, &pst); + } + //else PrintStrangeMenu(&pst); + } + free ((void *) pmNameBuff); + printf ("\n"); + } + + printf ("\n"); + printf ("\n+++++++++++++++++ DIALOG INFORMATION +++++++++++++++++++"); + printf ("\n"); + + nDialogs = GetContentsOfDialog (lpFile, &pdNameBuff); + + if (nDialogs == 0) + { + printf ("\n There are no Dialogs in This Application.\n"); + } + else + { + pst = pdNameBuff; + printf ("\nNumber of Dialogs = %4d (decimal)", nDialogs); + + printf ("\n"); + + for (i = 0; i < nDialogs; i++) + { + // Dialog ID print + printf ("\nName: %s", pst); + pst += strlen (pst) + 1; + PrintDialog (&pst); + } + free ((void *) pdNameBuff); + printf ("\n"); + } + } + + printf ("\n+++++++++++++++++++ IMPORTED FUNCTIONS +++++++++++++++++++"); + + nImportedModules = GetImportModuleNames (lpFile, &piNameBuff); + if (nImportedModules == 0) + { + printf ("\n There are no imported Functions in This Application.\n"); + } + else + { + pnstr = piNameBuff; + printf ("\nNumber of Imported Modules = %4d (decimal)\n", nImportedModules); + for (i = 0; i < nImportedModules; i++) + { + printf ("\n Import Module %03d: %s", i + 1, pnstr); + pnstr += strlen ((char *) (pnstr)) + 1; + } + + printf ("\n"); + printf ("\n+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++++"); + pnstr = piNameBuff; + for (i = 0; i < nImportedModules; i++) + { + printf ("\n\n Import Module %03d: %s \n", i + 1, pnstr); + nFunctions = GetImportFunctionNamesByModule (lpFile, pnstr, &pfNameBuff); + pnstr += strlen ((char *) (pnstr)) + 1; + pst = pfNameBuff; + for (j = 0; j < nFunctions; j++) + { + printf ("\nAddr:%08X hint(%04X) Name: %s", + (*(int *) pst), (*(short *) (pst + 4)), + //(pst+6)); + TranslateFunctionName (pst + 6)); + pst += strlen ((char *) (pst + 6)) + 1 + 6; + } + free ((void *) pfNameBuff); + } + free ((void *) piNameBuff); + } + + printf ("\n"); + printf ("\n+++++++++++++++++++ EXPORTED FUNCTIONS +++++++++++++++++++"); + + nExportedFunctions = GetExportFunctionNames (lpFile, &peNameBuff); + printf ("\nNumber of Exported Functions = %4d (decimal)\n", nExportedFunctions); + + if (nExportedFunctions > 0) + { + pst = peNameBuff; + + for (i = 0; i < nExportedFunctions; i++) + { + printf ("\nAddr:%08X Ord:%4d (%04Xh) Name: %s", + (*(int *) pst), (*(WORD *) (pst + 4)), (*(WORD *) (pst + 4)), + //(pst+6)); + TranslateFunctionName (pst + 6)); + pst += strlen ((char *) (pst + 6)) + 6 + 1; + } + free ((void *) peNameBuff); + } + + free ((void *) lpFile); + + return 0; +} + + +/* EOF */