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