1 //
2 // This program was written by Sang Cho, assistant professor at
3 //                                       the department of
4 //                                                                               computer science and engineering
5 //                                                                               chongju university
6 // this program is based on the program pefile.c
7 // which is written by Randy Kath(Microsoft Developmer Network Technology Group)
8 // in june 12, 1993.
9 // I have investigated P.E. file format as thoroughly as possible,
10 // but I cannot claim that I am an expert yet, so some of its information
11 // may give you wrong results.
12 //
13 //
14 //
15 // language used: djgpp
16 // date of creation: September 28, 1997
17 //
18 // date of first release: October 15, 1997
19 //
20 //
21 //      you can contact me: e-mail address: sangcho@alpha94.chongju.ac.kr
22 //                            hitel id: chokhas
23 //                        phone number: (0431) 229-8491    +82-431-229-8491
24 //
25 //
26 //
27 //   Copyright (C) 1997.                                 by Sang Cho.
28 //
29 //   Permission is granted to make and distribute verbatim copies of this
30 // program provided the copyright notice and this permission notice are
31 // preserved on all copies.
32 //
33 //
34 // File: pedump.c ( I included header file into source file. )
35 //
36 // LICENSE
37 //      Sources released under GNU General Public License version 2
38 //      or later by Mr. Sang Cho permission.
39 //
40 // REVISIONS
41 //      2000-04-23 (ea) Initial adaptation to GCC/MinGW/ROS.
42 //      2000-08-05 (ea) Initial raw adaptation done.
43 //
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include <string.h>
49 #include <setjmp.h>
50 #include <malloc.h>
51 #include <ctype.h>
52 
53 #ifndef bcopy
54 #define bcopy(s,d,z) memcpy((d),(s),(z))
55 #endif
56 
57 typedef char CHAR;
58 typedef short WCHAR;
59 typedef short SHORT;
60 typedef long LONG;
61 typedef unsigned short USHORT;
62 typedef unsigned long DWORD;
63 typedef int BOOL;
64 typedef unsigned char BYTE;
65 typedef unsigned short WORD;
66 typedef BYTE *PBYTE;
67 typedef WORD *PWORD;
68 typedef DWORD *PDWORD;
69 typedef void *LPVOID;
70 typedef int boolean;
71 
72 #define VOID                void
73 #define BOOLEAN             boolean
74 
75 #ifndef NULL
76 #define NULL                0
77 #endif
78 
79 #define FALSE               0
80 #define TRUE                1
81 #define CONST               const
82 #define LOWORD(l)           ((WORD)(l))
83 #define WINAPI		__stdcall
84 
85 //
86 // Image Format
87 //
88 
89 #define IMAGE_DOS_SIGNATURE                 0x5A4D	// MZ
90 #define IMAGE_OS2_SIGNATURE                 0x454E	// NE
91 #define IMAGE_OS2_SIGNATURE_LE              0x454C	// LE
92 #define IMAGE_VXD_SIGNATURE                 0x454C	// LE
93 #define IMAGE_NT_SIGNATURE                  0x00004550	// PE00
94 
95 typedef struct _IMAGE_DOS_HEADER
96   {				// DOS .EXE header
97 
98     WORD e_magic;		// Magic number
99 
100     WORD e_cblp;		// Bytes on last page of file
101 
102     WORD e_cp;			// Pages in file
103 
104     WORD e_crlc;		// Relocations
105 
106     WORD e_cparhdr;		// Size of header in paragraphs
107 
108     WORD e_minalloc;		// Minimum extra paragraphs needed
109 
110     WORD e_maxalloc;		// Maximum extra paragraphs needed
111 
112     WORD e_ss;			// Initial (relative) SS value
113 
114     WORD e_sp;			// Initial SP value
115 
116     WORD e_csum;		// Checksum
117 
118     WORD e_ip;			// Initial IP value
119 
120     WORD e_cs;			// Initial (relative) CS value
121 
122     WORD e_lfarlc;		// File address of relocation table
123 
124     WORD e_ovno;		// Overlay number
125 
126     WORD e_res[4];		// Reserved words
127 
128     WORD e_oemid;		// OEM identifier (for e_oeminfo)
129 
130     WORD e_oeminfo;		// OEM information; e_oemid specific
131 
132     WORD e_res2[10];		// Reserved words
133 
134     LONG e_lfanew;		// File address of new exe header
135 
136   }
137 IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
138 
139 //
140 // File header format.
141 //
142 
143 
144 
145 typedef struct _IMAGE_FILE_HEADER
146   {
147     WORD Machine;
148     WORD NumberOfSections;
149     DWORD TimeDateStamp;
150     DWORD PointerToSymbolTable;
151     DWORD NumberOfSymbols;
152     WORD SizeOfOptionalHeader;
153     WORD Characteristics;
154   }
155 IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
156 
157 #define IMAGE_SIZEOF_FILE_HEADER             20
158 
159 #define IMAGE_FILE_RELOCS_STRIPPED           0x0001	// Relocation info stripped from file.
160 #define IMAGE_FILE_EXECUTABLE_IMAGE          0x0002	// File is executable  (i.e. no unresolved externel references).
161 #define IMAGE_FILE_LINE_NUMS_STRIPPED        0x0004	// Line nunbers stripped from file.
162 #define IMAGE_FILE_LOCAL_SYMS_STRIPPED       0x0008	// Local symbols stripped from file.
163 #define IMAGE_FILE_BYTES_REVERSED_LO         0x0080	// Bytes of machine word are reversed.
164 #define IMAGE_FILE_32BIT_MACHINE             0x0100	// 32 bit word machine.
165 #define IMAGE_FILE_DEBUG_STRIPPED            0x0200	// Debugging info stripped from file in .DBG file
166 #define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   0x0400	// If Image is on removable media, copy and run from the swap file.
167 #define IMAGE_FILE_NET_RUN_FROM_SWAP         0x0800	// If Image is on Net, copy and run from the swap file.
168 #define IMAGE_FILE_SYSTEM                    0x1000	// System File.
169 #define IMAGE_FILE_DLL                       0x2000	// File is a DLL.
170 #define IMAGE_FILE_UP_SYSTEM_ONLY            0x4000	// File should only be run on a UP machine
171 #define IMAGE_FILE_BYTES_REVERSED_HI         0x8000	// Bytes of machine word are reversed.
172 
173 #define IMAGE_FILE_MACHINE_UNKNOWN           0
174 #define IMAGE_FILE_MACHINE_I386              0x14c	// Intel 386.
175 #define IMAGE_FILE_MACHINE_R3000             0x162	// MIPS little-endian, 0x160 big-endian
176 #define IMAGE_FILE_MACHINE_R4000             0x166	// MIPS little-endian
177 #define IMAGE_FILE_MACHINE_R10000            0x168	// MIPS little-endian
178 #define IMAGE_FILE_MACHINE_ALPHA             0x184	// Alpha_AXP
179 #define IMAGE_FILE_MACHINE_POWERPC           0x1F0	// IBM PowerPC Little-Endian
180 
181 
182 
183 //
184 // Directory format.
185 //
186 
187 typedef struct _IMAGE_DATA_DIRECTORY
188   {
189     DWORD VirtualAddress;
190     DWORD Size;
191 
192   }
193 IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
194 
195 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16
196 
197 //
198 // Optional header format.
199 //
200 
201 typedef struct _IMAGE_OPTIONAL_HEADER
202   {
203     //
204     // Standard fields.
205     //
206     WORD Magic;
207     BYTE MajorLinkerVersion;
208     BYTE MinorLinkerVersion;
209     DWORD SizeOfCode;
210     DWORD SizeOfInitializedData;
211     DWORD SizeOfUninitializedData;
212     DWORD AddressOfEntryPoint;
213     DWORD BaseOfCode;
214     DWORD BaseOfData;
215 
216     //
217     // NT additional fields.
218     //
219 
220     DWORD ImageBase;
221     DWORD SectionAlignment;
222     DWORD FileAlignment;
223     WORD MajorOperatingSystemVersion;
224     WORD MinorOperatingSystemVersion;
225     WORD MajorImageVersion;
226     WORD MinorImageVersion;
227     WORD MajorSubsystemVersion;
228     WORD MinorSubsystemVersion;
229     DWORD Win32VersionValue;
230     DWORD SizeOfImage;
231     DWORD SizeOfHeaders;
232     DWORD CheckSum;
233     WORD Subsystem;
234     WORD DllCharacteristics;
235     DWORD SizeOfStackReserve;
236     DWORD SizeOfStackCommit;
237     DWORD SizeOfHeapReserve;
238     DWORD SizeOfHeapCommit;
239     DWORD LoaderFlags;
240     DWORD NumberOfRvaAndSizes;
241     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
242 
243   }
244 IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
245 
246 
247 typedef struct _IMAGE_NT_HEADERS
248   {
249     DWORD Signature;
250     IMAGE_FILE_HEADER FileHeader;
251     IMAGE_OPTIONAL_HEADER OptionalHeader;
252 
253   }
254 IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
255 
256 
257 // Directory Entries
258 
259 #define IMAGE_DIRECTORY_ENTRY_EXPORT         0	// Export Directory
260 #define IMAGE_DIRECTORY_ENTRY_IMPORT         1	// Import Directory
261 #define IMAGE_DIRECTORY_ENTRY_RESOURCE       2	// Resource Directory
262 #define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3	// Exception Directory
263 #define IMAGE_DIRECTORY_ENTRY_SECURITY       4	// Security Directory
264 #define IMAGE_DIRECTORY_ENTRY_BASERELOC      5	// Base Relocation Table
265 #define IMAGE_DIRECTORY_ENTRY_DEBUG          6	// Debug Directory
266 #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7	// Description String
267 #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8	// Machine Value (MIPS GP)
268 #define IMAGE_DIRECTORY_ENTRY_TLS            9	// TLS Directory
269 #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG   10	// Load Configuration Directory
270 #define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT  11	// Bound Import Directory in headers
271 #define IMAGE_DIRECTORY_ENTRY_IAT           12	// Import Address Table
272 
273 //
274 // Section header format.
275 //
276 
277 #define IMAGE_SIZEOF_SHORT_NAME              8
278 
279 typedef struct _IMAGE_SECTION_HEADER
280   {
281     BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
282     union
283       {
284 	DWORD PhysicalAddress;
285 	DWORD VirtualSize;
286       }
287     Misc;
288     DWORD VirtualAddress;
289     DWORD SizeOfRawData;
290     DWORD PointerToRawData;
291     DWORD PointerToRelocations;
292     DWORD PointerToLinenumbers;
293     WORD NumberOfRelocations;
294     WORD NumberOfLinenumbers;
295     DWORD Characteristics;
296 
297   }
298 IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
299 
300 #define IMAGE_SIZEOF_SECTION_HEADER          40
301 
302 
303 //
304 // Export Format
305 //
306 
307 typedef struct _IMAGE_EXPORT_DIRECTORY
308   {
309     DWORD Characteristics;
310     DWORD TimeDateStamp;
311     WORD MajorVersion;
312     WORD MinorVersion;
313     DWORD Name;
314     DWORD Base;
315     DWORD NumberOfFunctions;
316     DWORD NumberOfNames;
317     PDWORD *AddressOfFunctions;
318     PDWORD *AddressOfNames;
319     PWORD *AddressOfNameOrdinals;
320 
321   }
322 IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
323 
324 //
325 // Import Format
326 //
327 
328 typedef struct _IMAGE_IMPORT_BY_NAME
329   {
330     WORD Hint;
331     BYTE Name[1];
332 
333   }
334 IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
335 
336 #define IMAGE_ORDINAL_FLAG 0x80000000
337 #define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
338 
339 
340 //
341 // Resource Format.
342 //
343 
344 //
345 // Resource directory consists of two counts, following by a variable length
346 // array of directory entries.  The first count is the number of entries at
347 // beginning of the array that have actual names associated with each entry.
348 // The entries are in ascending order, case insensitive strings.  The second
349 // count is the number of entries that immediately follow the named entries.
350 // This second count identifies the number of entries that have 16-bit integer
351 // Ids as their name.  These entries are also sorted in ascending order.
352 //
353 // This structure allows fast lookup by either name or number, but for any
354 // given resource entry only one form of lookup is supported, not both.
355 // This is consistant with the syntax of the .RC file and the .RES file.
356 //
357 
358 // Predefined resource types ... there may be some more, but I don't have
359 //                               the information yet.  .....sang cho.....
360 
361 #define    RT_NEWRESOURCE   0x2000
362 #define    RT_ERROR         0x7fff
363 #define    RT_CURSOR        1
364 #define    RT_BITMAP        2
365 #define    RT_ICON          3
366 #define    RT_MENU          4
367 #define    RT_DIALOG        5
368 #define    RT_STRING        6
369 #define    RT_FONTDIR       7
370 #define    RT_FONT          8
371 #define    RT_ACCELERATORS  9
372 #define    RT_RCDATA        10
373 #define    RT_MESSAGETABLE  11
374 #define    RT_GROUP_CURSOR  12
375 #define    RT_GROUP_ICON    14
376 #define    RT_VERSION       16
377 #define    NEWBITMAP        (RT_BITMAP|RT_NEWRESOURCE)
378 #define    NEWMENU          (RT_MENU|RT_NEWRESOURCE)
379 #define    NEWDIALOG        (RT_DIALOG|RT_NEWRESOURCE)
380 
381 
382 typedef struct _IMAGE_RESOURCE_DIRECTORY
383   {
384     DWORD Characteristics;
385     DWORD TimeDateStamp;
386     WORD MajorVersion;
387     WORD MinorVersion;
388     WORD NumberOfNamedEntries;
389     WORD NumberOfIdEntries;
390 //      IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[1];
391 
392   }
393 IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
394 
395 #define IMAGE_RESOURCE_NAME_IS_STRING        0x80000000
396 #define IMAGE_RESOURCE_DATA_IS_DIRECTORY     0x80000000
397 
398 //
399 // Each directory contains the 32-bit Name of the entry and an offset,
400 // relative to the beginning of the resource directory of the data associated
401 // with this directory entry.  If the name of the entry is an actual text
402 // string instead of an integer Id, then the high order bit of the name field
403 // is set to one and the low order 31-bits are an offset, relative to the
404 // beginning of the resource directory of the string, which is of type
405 // IMAGE_RESOURCE_DIRECTORY_STRING.  Otherwise the high bit is clear and the
406 // low-order 16-bits are the integer Id that identify this resource directory
407 // entry. If the directory entry is yet another resource directory (i.e. a
408 // subdirectory), then the high order bit of the offset field will be
409 // set to indicate this.  Otherwise the high bit is clear and the offset
410 // field points to a resource data entry.
411 //
412 
413 typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY
414   {
415     DWORD Name;
416     DWORD OffsetToData;
417 
418   }
419 IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
420 
421 //
422 // For resource directory entries that have actual string names, the Name
423 // field of the directory entry points to an object of the following type.
424 // All of these string objects are stored together after the last resource
425 // directory entry and before the first resource data object.  This minimizes
426 // the impact of these variable length objects on the alignment of the fixed
427 // size directory entry objects.
428 //
429 
430 typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING
431   {
432     WORD Length;
433     CHAR NameString[1];
434 
435   }
436 IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING;
437 
438 
439 typedef struct _IMAGE_RESOURCE_DIR_STRING_U
440   {
441     WORD Length;
442     WCHAR NameString[1];
443 
444   }
445 IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
446 
447 
448 //
449 // Each resource data entry describes a leaf node in the resource directory
450 // tree.  It contains an offset, relative to the beginning of the resource
451 // directory of the data for the resource, a size field that gives the number
452 // of bytes of data at that offset, a CodePage that should be used when
453 // decoding code point values within the resource data.  Typically for new
454 // applications the code page would be the unicode code page.
455 //
456 
457 typedef struct _IMAGE_RESOURCE_DATA_ENTRY
458   {
459     DWORD OffsetToData;
460     DWORD Size;
461     DWORD CodePage;
462     DWORD Reserved;
463 
464   }
465 IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
466 
467 
468 //  Menu Resources       ... added by .....sang cho....
469 
470 // Menu resources are composed of a menu header followed by a sequential list
471 // of menu items. There are two types of menu items: pop-ups and normal menu
472 // itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with
473 // an empty name, zero ID, and zero flags.
474 
475 typedef struct _IMAGE_MENU_HEADER
476   {
477     WORD wVersion;		// Currently zero
478 
479     WORD cbHeaderSize;		// Also zero
480 
481   }
482 IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER;
483 
484 typedef struct _IMAGE_POPUP_MENU_ITEM
485   {
486     WORD fItemFlags;
487     WCHAR szItemText[1];
488 
489   }
490 IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM;
491 
492 typedef struct _IMAGE_NORMAL_MENU_ITEM
493   {
494     WORD fItemFlags;
495     WORD wMenuID;
496     WCHAR szItemText[1];
497 
498   }
499 IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM;
500 
501 #define GRAYED       0x0001	// GRAYED keyword
502 #define INACTIVE     0x0002	// INACTIVE keyword
503 #define BITMAP       0x0004	// BITMAP keyword
504 #define OWNERDRAW    0x0100	// OWNERDRAW keyword
505 #define CHECKED      0x0008	// CHECKED keyword
506 #define POPUP        0x0010	// used internally
507 #define MENUBARBREAK 0x0020	// MENUBARBREAK keyword
508 #define MENUBREAK    0x0040	// MENUBREAK keyword
509 #define ENDMENU      0x0080	// used internally
510 
511 
512 // Dialog Box Resources .................. added by sang cho.
513 
514 // A dialog box is contained in a single resource and has a header and
515 // a portion repeated for each control in the dialog box.
516 // The item DWORD IStyle is a standard window style composed of flags found
517 // in WINDOWS.H.
518 // The default style for a dialog box is:
519 // WS_POPUP | WS_BORDER | WS_SYSMENU
520 //
521 // The itme marked "Name or Ordinal" are :
522 // If the first word is an 0xffff, the next two bytes contain an ordinal ID.
523 // Otherwise, the first one or more WORDS contain a double-null-terminated string.
524 // An empty string is represented by a single WORD zero in the first location.
525 //
526 // The WORD wPointSize and WCHAR szFontName entries are present if the FONT
527 // statement was included for the dialog box. This can be detected by checking
528 // the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these
529 // entries will be present.
530 
531 typedef struct _IMAGE_DIALOG_BOX_HEADER1
532   {
533     DWORD IStyle;
534     DWORD IExtendedStyle;	// New for Windows NT
535 
536     WORD nControls;		// Number of Controls
537 
538     WORD x;
539     WORD y;
540     WORD cx;
541     WORD cy;
542 //      N_OR_O MenuName;         // Name or Ordinal ID
543     //      N_OR_O ClassName;                // Name or Ordinal ID
544     //      WCHAR  szCaption[];
545     //      WORD   wPointSize;       // Only here if FONT set for dialog
546     //      WCHAR  szFontName[];     // This too
547   }
548 IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER;
549 
550 typedef union _NAME_OR_ORDINAL
551   {				// Name or Ordinal ID
552 
553     struct _ORD_ID
554       {
555 	WORD flgId;
556 	WORD Id;
557       }
558     ORD_ID;
559     WCHAR szName[1];
560   }
561 NAME_OR_ORDINAL, *PNAME_OR_ORDINAL;
562 
563 // The data for each control starts on a DWORD boundary (which may require
564 // some padding from the previous control), and its format is as follows:
565 
566 typedef struct _IMAGE_CONTROL_DATA
567   {
568     DWORD IStyle;
569     DWORD IExtendedStyle;
570     WORD x;
571     WORD y;
572     WORD cx;
573     WORD cy;
574     WORD wId;
575 //  N_OR_O  ClassId;
576     //  N_OR_O  Text;
577     //  WORD    nExtraStuff;
578   }
579 IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA;
580 
581 #define BUTTON       0x80
582 #define EDIT         0x81
583 #define STATIC       0x82
584 #define LISTBOX      0x83
585 #define SCROLLBAR    0x84
586 #define COMBOBOX     0x85
587 
588 // The various statements used in a dialog script are all mapped to these
589 // classes along with certain modifying styles. The values for these styles
590 // can be found in WINDOWS.H. All dialog controls have the default styles
591 // of WS_CHILD and WS_VISIBLE. A list of the default styles used follows:
592 //
593 // Statement           Default Class         Default Styles
594 // CONTROL             None                  WS_CHILD|WS_VISIBLE
595 // LTEXT               STATIC                ES_LEFT
596 // RTEXT               STATIC                ES_RIGHT
597 // CTEXT               STATIC                ES_CENTER
598 // LISTBOX             LISTBOX               WS_BORDER|LBS_NOTIFY
599 // CHECKBOX            BUTTON                BS_CHECKBOX|WS_TABSTOP
600 // PUSHBUTTON          BUTTON                BS_PUSHBUTTON|WS_TABSTOP
601 // GROUPBOX            BUTTON                BS_GROUPBOX
602 // DEFPUSHBUTTON       BUTTON                BS_DFPUSHBUTTON|WS_TABSTOP
603 // RADIOBUTTON         BUTTON                BS_RADIOBUTTON
604 // AUTOCHECKBOX        BUTTON                BS_AUTOCHECKBOX
605 // AUTO3STATE          BUTTON                BS_AUTO3STATE
606 // AUTORADIOBUTTON     BUTTON                BS_AUTORADIOBUTTON
607 // PUSHBOX             BUTTON                BS_PUSHBOX
608 // STATE3              BUTTON                BS_3STATE
609 // EDITTEXT            EDIT                  ES_LEFT|WS_BORDER|WS_TABSTOP
610 // COMBOBOX            COMBOBOX              None
611 // ICON                STATIC                SS_ICON
612 // SCROLLBAR           SCROLLBAR             None
613 ///
614 
615 #define WS_OVERLAPPED   0x00000000L
616 #define WS_POPUP        0x80000000L
617 #define WS_CHILD        0x40000000L
618 #define WS_CLIPSIBLINGS 0x04000000L
619 #define WS_CLIPCHILDREN 0x02000000L
620 #define WS_VISIBLE      0x10000000L
621 #define WS_DISABLED     0x08000000L
622 #define WS_MINIMIZE     0x20000000L
623 #define WS_MAXIMIZE     0x01000000L
624 #define WS_CAPTION      0x00C00000L
625 #define WS_BORDER       0x00800000L
626 #define WS_DLGFRAME     0x00400000L
627 #define WS_VSCROLL      0x00200000L
628 #define WS_HSCROLL      0x00100000L
629 #define WS_SYSMENU      0x00080000L
630 #define WS_THICKFRAME   0x00040000L
631 #define WS_MINIMIZEBOX  0x00020000L
632 #define WS_MAXIMIZEBOX  0x00010000L
633 #define WS_GROUP        0x00020000L
634 #define WS_TABSTOP      0x00010000L
635 
636 // other aliases
637 #define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
638 #define WS_POPUPWINDOW  (WS_POPUP | WS_BORDER | WS_SYSMENU)
639 #define WS_CHILDWINDOW  (WS_CHILD)
640 #define WS_TILED        WS_OVERLAPPED
641 #define WS_ICONIC       WS_MINIMIZE
642 #define WS_SIZEBOX      WS_THICKFRAME
643 #define WS_TILEDWINDOW  WS_OVERLAPPEDWINDOW
644 
645 #define WS_EX_DLGMODALFRAME     0x00000001L
646 #define WS_EX_NOPARENTNOTIFY    0x00000004L
647 #define WS_EX_TOPMOST           0x00000008L
648 #define WS_EX_ACCEPTFILES       0x00000010L
649 #define WS_EX_TRANSPARENT       0x00000020L
650 
651 #define BS_PUSHBUTTON           0x00000000L
652 #define BS_DEFPUSHBUTTON        0x00000001L
653 #define BS_CHECKBOX             0x00000002L
654 #define BS_AUTOCHECKBOX         0x00000003L
655 #define BS_RADIOBUTTON          0x00000004L
656 #define BS_3STATE               0x00000005L
657 #define BS_AUTO3STATE           0x00000006L
658 #define BS_GROUPBOX             0x00000007L
659 #define BS_USERBUTTON           0x00000008L
660 #define BS_AUTORADIOBUTTON      0x00000009L
661 #define BS_OWNERDRAW            0x0000000BL
662 #define BS_LEFTTEXT             0x00000020L
663 
664 #define ES_LEFT         0x00000000L
665 #define ES_CENTER       0x00000001L
666 #define ES_RIGHT        0x00000002L
667 #define ES_MULTILINE    0x00000004L
668 #define ES_UPPERCASE    0x00000008L
669 #define ES_LOWERCASE    0x00000010L
670 #define ES_PASSWORD     0x00000020L
671 #define ES_AUTOVSCROLL  0x00000040L
672 #define ES_AUTOHSCROLL  0x00000080L
673 #define ES_NOHIDESEL    0x00000100L
674 #define ES_OEMCONVERT   0x00000400L
675 #define ES_READONLY     0x00000800L
676 #define ES_WANTRETURN   0x00001000L
677 
678 #define LBS_NOTIFY            0x0001L
679 #define LBS_SORT              0x0002L
680 #define LBS_NOREDRAW          0x0004L
681 #define LBS_MULTIPLESEL       0x0008L
682 #define LBS_OWNERDRAWFIXED    0x0010L
683 #define LBS_OWNERDRAWVARIABLE 0x0020L
684 #define LBS_HASSTRINGS        0x0040L
685 #define LBS_USETABSTOPS       0x0080L
686 #define LBS_NOINTEGRALHEIGHT  0x0100L
687 #define LBS_MULTICOLUMN       0x0200L
688 #define LBS_WANTKEYBOARDINPUT 0x0400L
689 #define LBS_EXTENDEDSEL       0x0800L
690 #define LBS_DISABLENOSCROLL   0x1000L
691 
692 #define SS_LEFT             0x00000000L
693 #define SS_CENTER           0x00000001L
694 #define SS_RIGHT            0x00000002L
695 #define SS_ICON             0x00000003L
696 #define SS_BLACKRECT        0x00000004L
697 #define SS_GRAYRECT         0x00000005L
698 #define SS_WHITERECT        0x00000006L
699 #define SS_BLACKFRAME       0x00000007L
700 #define SS_GRAYFRAME        0x00000008L
701 #define SS_WHITEFRAME       0x00000009L
702 #define SS_SIMPLE           0x0000000BL
703 #define SS_LEFTNOWORDWRAP   0x0000000CL
704 #define SS_BITMAP           0x0000000EL
705 
706 //
707 // Debug Format
708 //
709 
710 typedef struct _IMAGE_DEBUG_DIRECTORY
711   {
712     DWORD Characteristics;
713     DWORD TimeDateStamp;
714     WORD MajorVersion;
715     WORD MinorVersion;
716     DWORD Type;
717     DWORD SizeOfData;
718     DWORD AddressOfRawData;
719     DWORD PointerToRawData;
720   }
721 IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
722 
723 #define IMAGE_DEBUG_TYPE_UNKNOWN          0
724 #define IMAGE_DEBUG_TYPE_COFF             1
725 #define IMAGE_DEBUG_TYPE_CODEVIEW         2
726 #define IMAGE_DEBUG_TYPE_FPO              3
727 #define IMAGE_DEBUG_TYPE_MISC             4
728 #define IMAGE_DEBUG_TYPE_EXCEPTION        5
729 #define IMAGE_DEBUG_TYPE_FIXUP            6
730 #define IMAGE_DEBUG_TYPE_OMAP_TO_SRC      7
731 #define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC    8
732 
733 
734 typedef struct _IMAGE_DEBUG_MISC
735   {
736     DWORD DataType;		// type of misc data, see defines
737 
738     DWORD Length;		// total length of record, rounded to four
739     // byte multiple.
740 
741     BOOLEAN Unicode;		// TRUE if data is unicode string
742 
743     BYTE Reserved[3];
744     BYTE Data[1];		// Actual data
745 
746   }
747 IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;
748 
749 
750 //
751 // Debugging information can be stripped from an image file and placed
752 // in a separate .DBG file, whose file name part is the same as the
753 // image file name part (e.g. symbols for CMD.EXE could be stripped
754 // and placed in CMD.DBG).  This is indicated by the IMAGE_FILE_DEBUG_STRIPPED
755 // flag in the Characteristics field of the file header.  The beginning of
756 // the .DBG file contains the following structure which captures certain
757 // information from the image file.  This allows a debug to proceed even if
758 // the original image file is not accessable.  This header is followed by
759 // zero of more IMAGE_SECTION_HEADER structures, followed by zero or more
760 // IMAGE_DEBUG_DIRECTORY structures.  The latter structures and those in
761 // the image file contain file offsets relative to the beginning of the
762 // .DBG file.
763 //
764 // If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure
765 // is left in the image file, but not mapped.  This allows a debugger to
766 // compute the name of the .DBG file, from the name of the image in the
767 // IMAGE_DEBUG_MISC structure.
768 //
769 
770 typedef struct _IMAGE_SEPARATE_DEBUG_HEADER
771   {
772     WORD Signature;
773     WORD Flags;
774     WORD Machine;
775     WORD Characteristics;
776     DWORD TimeDateStamp;
777     DWORD CheckSum;
778     DWORD ImageBase;
779     DWORD SizeOfImage;
780     DWORD NumberOfSections;
781     DWORD ExportedNamesSize;
782     DWORD DebugDirectorySize;
783     DWORD SectionAlignment;
784     DWORD Reserved[2];
785   }
786 IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;
787 
788 #define IMAGE_SEPARATE_DEBUG_SIGNATURE  0x4944
789 
790 #define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000
791 #define IMAGE_SEPARATE_DEBUG_MISMATCH   0x8000	// when DBG was updated, the
792 						// old checksum didn't match.
793 
794 
795 //
796 // End Image Format
797 //
798 
799 
800 #define SIZE_OF_NT_SIGNATURE	sizeof (DWORD)
801 #define MAXRESOURCENAME 	13
802 
803 /* global macros to define header offsets into file */
804 /* offset to PE file signature                                 */
805 #define NTSIGNATURE(a) ((LPVOID)((BYTE *)a		     +	\
806 			((PIMAGE_DOS_HEADER)a)->e_lfanew))
807 
808 /* DOS header identifies the NT PEFile signature dword
809    the PEFILE header exists just after that dword              */
810 #define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
811 			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
812 			 SIZE_OF_NT_SIGNATURE))
813 
814 /* PE optional header is immediately after PEFile header       */
815 #define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
816 			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
817 			 SIZE_OF_NT_SIGNATURE		     +	\
818 			 sizeof (IMAGE_FILE_HEADER)))
819 
820 /* section headers are immediately after PE optional header    */
821 #define SECHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
822 			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
823 			 SIZE_OF_NT_SIGNATURE		     +	\
824 			 sizeof (IMAGE_FILE_HEADER)	     +	\
825 			 sizeof (IMAGE_OPTIONAL_HEADER)))
826 
827 
828 typedef struct tagImportDirectory
829   {
830     DWORD dwRVAFunctionNameList;
831     DWORD dwUseless1;
832     DWORD dwUseless2;
833     DWORD dwRVAModuleName;
834     DWORD dwRVAFunctionAddressList;
835   }
836 IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;
837 
838 
839 /* global prototypes for functions in pefile.c */
840 /* PE file header info */
841 BOOL WINAPI GetDosHeader (LPVOID, PIMAGE_DOS_HEADER);
842 DWORD WINAPI ImageFileType (LPVOID);
843 BOOL WINAPI GetPEFileHeader (LPVOID, PIMAGE_FILE_HEADER);
844 
845 /* PE optional header info */
846 BOOL WINAPI GetPEOptionalHeader (LPVOID, PIMAGE_OPTIONAL_HEADER);
847 LPVOID WINAPI GetModuleEntryPoint (LPVOID);
848 int WINAPI NumOfSections (LPVOID);
849 LPVOID WINAPI GetImageBase (LPVOID);
850 LPVOID WINAPI ImageDirectoryOffset (LPVOID, DWORD);
851 LPVOID WINAPI ImageDirectorySection (LPVOID, DWORD);
852 
853 /* PE section header info */
854 //int   WINAPI GetSectionNames (LPVOID, HANDLE, char **);
855 int WINAPI GetSectionNames (LPVOID, char **);
856 BOOL WINAPI GetSectionHdrByName (LPVOID, PIMAGE_SECTION_HEADER, char *);
857 
858 //
859 // structur to store string tokens
860 //
861 typedef struct _Str_P
862   {
863     char flag;			// string_flag '@' or '%' or '#'
864 
865     char *pos;			// starting postion of string
866 
867     int length;			// length of string
868 
869     BOOL wasString;		// if it were stringMode or not
870 
871   }
872 Str_P;
873 
874 /* import section info */
875 int WINAPI GetImportModuleNames (LPVOID, char **);
876 int WINAPI GetImportFunctionNamesByModule (LPVOID, char *, char **);
877 
878 // import function name reporting
879 int WINAPI GetStringLength (char *);
880 void WINAPI GetPreviousParamString (char *, char *);
881 void WINAPI TranslateParameters (char **, char **, char **);
882 BOOL WINAPI StringExpands (char **, char **, char **, Str_P *);
883 char * WINAPI TranslateFunctionName (char *);
884 
885 /* export section info */
886 int WINAPI GetExportFunctionNames (LPVOID, char **);
887 
888 /* resource section info */
889 int WINAPI GetNumberOfResources (LPVOID);
890 int WINAPI GetListOfResourceTypes (LPVOID, char **);
891 int WINAPI MenuScan (int *, WORD **);
892 int WINAPI MenuFill (char **, WORD **);
893 void WINAPI StrangeMenuFill (char **, WORD **, int);
894 int WINAPI GetContentsOfMenu (LPVOID, char **);
895 int WINAPI PrintMenu (int, char **);
896 int WINAPI PrintStrangeMenu (char **);
897 int WINAPI dumpMenu (char **psz, int size);
898 
899 /* debug section info */
900 BOOL WINAPI IsDebugInfoStripped (LPVOID);
901 int WINAPI RetrieveModuleName (LPVOID, char **);
902 BOOL WINAPI IsDebugFile (LPVOID);
903 BOOL WINAPI GetSeparateDebugHeader (LPVOID, PIMAGE_SEPARATE_DEBUG_HEADER);
904 
905 
906 /**********************************************************************
907  * NAME
908  *
909  * DESCRIPTION
910  *	Copy DOS header information to structure.
911  *
912  * ARGUMENTS
913  */
914 BOOL WINAPI
915 GetDosHeader (
916 	       LPVOID lpFile,
917 	       PIMAGE_DOS_HEADER pHeader
918 )
919 {
920   /*
921    * DOS header represents first structure
922    * of bytes in PE image file.
923    */
924   if ((WORD) IMAGE_DOS_SIGNATURE == *(WORD *) lpFile)
925     {
926       bcopy (
927 	      lpFile,
928 	      (LPVOID) pHeader,
929 	      sizeof (IMAGE_DOS_HEADER)
930 	);
931       return TRUE;
932     }
933   return FALSE;
934 }
935 
936 
937 
938 
939 /* return file signature */
940 DWORD WINAPI
941 ImageFileType (
942 		LPVOID lpFile)
943 {
944   /* dos file signature comes first */
945   if (*(USHORT *) lpFile == IMAGE_DOS_SIGNATURE)
946     {
947       /* determine location of PE File header from dos header */
948       if (LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE ||
949 	  LOWORD (*(DWORD *) NTSIGNATURE (lpFile)) == IMAGE_OS2_SIGNATURE_LE)
950 	return (DWORD) LOWORD (*(DWORD *) NTSIGNATURE (lpFile));
951 
952       else if (*(DWORD *) NTSIGNATURE (lpFile) == IMAGE_NT_SIGNATURE)
953 	return IMAGE_NT_SIGNATURE;
954 
955       else
956 	return IMAGE_DOS_SIGNATURE;
957     }
958 
959   else
960     /* unknown file type */
961     return 0;
962 }
963 
964 
965 
966 
967 /* copy file header information to structure */
968 BOOL WINAPI
969 GetPEFileHeader (
970 		  LPVOID lpFile,
971 		  PIMAGE_FILE_HEADER pHeader)
972 {
973   /* file header follows dos header */
974   if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
975     bcopy (PEFHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_FILE_HEADER));
976   else
977     return FALSE;
978 
979   return TRUE;
980 }
981 
982 
983 
984 
985 
986 /* copy optional header info to structure */
987 BOOL WINAPI
988 GetPEOptionalHeader (
989 		      LPVOID lpFile,
990 		      PIMAGE_OPTIONAL_HEADER pHeader)
991 {
992   /* optional header follows file header and dos header */
993   if (ImageFileType (lpFile) == IMAGE_NT_SIGNATURE)
994     bcopy (OPTHDROFFSET (lpFile), (LPVOID) pHeader, sizeof (IMAGE_OPTIONAL_HEADER));
995   else
996     return FALSE;
997 
998   return TRUE;
999 }
1000 
1001 
1002 
1003 
1004 /* function returns the entry point for an exe module lpFile must
1005    be a memory mapped file pointer to the beginning of the image file */
1006 LPVOID WINAPI
1007 GetModuleEntryPoint (
1008 		      LPVOID lpFile)
1009 {
1010   PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);
1011 
1012   if (poh != NULL)
1013     return (LPVOID) (poh->AddressOfEntryPoint);
1014   else
1015     return NULL;
1016 }
1017 
1018 
1019 
1020 
1021 /* return the total number of sections in the module */
1022 int WINAPI
1023 NumOfSections (
1024 		LPVOID lpFile)
1025 {
1026   /* number os sections is indicated in file header */
1027   return ((int) ((PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile))->NumberOfSections);
1028 }
1029 
1030 
1031 
1032 
1033 /* retrieve entry point */
1034 LPVOID WINAPI
1035 GetImageBase (
1036 	       LPVOID lpFile)
1037 {
1038   PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);
1039 
1040   if (poh != NULL)
1041     return (LPVOID) (poh->ImageBase);
1042   else
1043     return NULL;
1044 }
1045 
1046 
1047 
1048 //
1049 // This function is written by sang cho
1050 //                                                 .. october 5, 1997
1051 //
1052 /* function returns the actual address of given RVA,      lpFile must
1053    be a memory mapped file pointer to the beginning of the image file */
1054 LPVOID WINAPI
1055 GetActualAddress (
1056 		   LPVOID lpFile,
1057 		   DWORD dwRVA)
1058 {
1059 //    PIMAGE_OPTIONAL_HEADER   poh = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET (lpFile);
1060   PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);
1061   int nSections = NumOfSections (lpFile);
1062   int i = 0;
1063 
1064   if (dwRVA == 0)
1065     return NULL;
1066   if (dwRVA & 0x80000000)
1067     {
1068       //return (LPVOID)dwRVA;
1069       printf ("\n$$ what is going on $$");
1070       exit (0);
1071     }
1072 
1073   /* locate section containing image directory */
1074   while (i++ < nSections)
1075     {
1076       if (psh->VirtualAddress <= (DWORD) dwRVA &&
1077 	  psh->VirtualAddress + psh->SizeOfRawData > (DWORD) dwRVA)
1078 	break;
1079       psh++;
1080     }
1081 
1082   if (i > nSections)
1083     return NULL;
1084 
1085   /* return image import directory offset */
1086   return (LPVOID) (((int) lpFile + (int) dwRVA - psh->VirtualAddress) +
1087 		   (int) psh->PointerToRawData);
1088 }
1089 
1090 
1091 //
1092 // This function is modified by sang cho
1093 //
1094 //
1095 /* return offset to specified IMAGE_DIRECTORY entry */
1096 LPVOID WINAPI
1097 ImageDirectoryOffset (
1098 		       LPVOID lpFile,
1099 		       DWORD dwIMAGE_DIRECTORY)
1100 {
1101   PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);
1102   PIMAGE_SECTION_HEADER psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);
1103   int nSections = NumOfSections (lpFile);
1104   int i = 0;
1105   LPVOID VAImageDir;
1106 
1107   /* must be 0 thru (NumberOfRvaAndSizes-1) */
1108   if (dwIMAGE_DIRECTORY >= poh->NumberOfRvaAndSizes)
1109     return NULL;
1110 
1111   /* locate specific image directory's relative virtual address */
1112   VAImageDir = (LPVOID) poh->DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
1113 
1114   if (VAImageDir == NULL)
1115     return NULL;
1116   /* locate section containing image directory */
1117   while (i++ < nSections)
1118     {
1119       if (psh->VirtualAddress <= (DWORD) VAImageDir &&
1120 	  psh->VirtualAddress + psh->SizeOfRawData > (DWORD) VAImageDir)
1121 	break;
1122       psh++;
1123     }
1124 
1125   if (i > nSections)
1126     return NULL;
1127 
1128   /* return image import directory offset */
1129   return (LPVOID) (((int) lpFile + (int) VAImageDir - psh->VirtualAddress) +
1130 		   (int) psh->PointerToRawData);
1131 }
1132 
1133 
1134 /* function retrieve names of all the sections in the file */
1135 int WINAPI
1136 GetSectionNames (
1137 		  LPVOID lpFile,
1138 		  char **pszSections)
1139 {
1140   int nSections = NumOfSections (lpFile);
1141   int i, nCnt = 0;
1142   PIMAGE_SECTION_HEADER psh;
1143   char *ps;
1144 
1145 
1146   if (ImageFileType (lpFile) != IMAGE_NT_SIGNATURE ||
1147       (psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) == NULL)
1148     return 0;
1149 
1150   /* count the number of chars used in the section names */
1151   for (i = 0; i < nSections; i++)
1152     nCnt += strlen ((char *)psh[i].Name) + 1;
1153 
1154   /* allocate space for all section names from heap */
1155   ps = *pszSections = (char *) calloc (nCnt, 1);
1156 
1157 
1158   for (i = 0; i < nSections; i++)
1159     {
1160       strcpy (ps, (char *)psh[i].Name);
1161       ps += strlen ((char *)psh[i].Name) + 1;
1162     }
1163 
1164   return nCnt;
1165 }
1166 
1167 
1168 
1169 
1170 /* function gets the function header for a section identified by name */
1171 BOOL WINAPI
1172 GetSectionHdrByName (
1173 		      LPVOID lpFile,
1174 		      IMAGE_SECTION_HEADER * sh,
1175 		      char *szSection)
1176 {
1177   PIMAGE_SECTION_HEADER psh;
1178   int nSections = NumOfSections (lpFile);
1179   int i;
1180 
1181 
1182   if ((psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile)) != NULL)
1183     {
1184       /* find the section by name */
1185       for (i = 0; i < nSections; i++)
1186 	{
1187 	  if (!strcmp ((char *)psh->Name, szSection))
1188 	    {
1189 	      /* copy data to header */
1190 	      bcopy ((LPVOID) psh, (LPVOID) sh, sizeof (IMAGE_SECTION_HEADER));
1191 	      return TRUE;
1192 	    }
1193 	  else
1194 	    psh++;
1195 	}
1196     }
1197   return FALSE;
1198 }
1199 
1200 
1201 
1202 //
1203 // This function is modified by sang cho
1204 //
1205 //
1206 /* get import modules names separated by null terminators, return module count */
1207 int WINAPI
1208 GetImportModuleNames (
1209 		       LPVOID lpFile,
1210 		       char **pszModules)
1211 {
1212   PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1213   ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
1214   //
1215   // sometimes there may be no section for idata or edata
1216   // instead rdata or data section may contain these sections ..
1217   // or even module names or function names are in different section.
1218   // so that's why we need to get actual address of RVAs each time.
1219   //         ...................sang cho..................
1220   //
1221   // PIMAGE_SECTION_HEADER     psh = (PIMAGE_SECTION_HEADER)
1222   // ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
1223   // BYTE                  *pData = (BYTE *)pid;
1224   //      DWORD            *pdw = (DWORD *)pid;
1225   int nCnt = 0, nSize = 0, i;
1226   char *pModule[1024];		/* hardcoded maximum number of modules?? */
1227   char *psz;
1228 
1229   if (pid == NULL)
1230     return 0;
1231 
1232   // pData = (BYTE *)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
1233 
1234   /* extract all import modules */
1235   while (pid->dwRVAModuleName)
1236     {
1237       /* allocate temporary buffer for absolute string offsets */
1238       //pModule[nCnt] = (char *)(pData + pid->dwRVAModuleName);
1239       pModule[nCnt] = (char *) GetActualAddress (lpFile, pid->dwRVAModuleName);
1240       nSize += strlen (pModule[nCnt]) + 1;
1241 
1242       /* increment to the next import directory entry */
1243       pid++;
1244       nCnt++;
1245     }
1246 
1247   /* copy all strings to one chunk of memory */
1248   *pszModules = (char *) calloc (nSize, 1);
1249   psz = *pszModules;
1250   for (i = 0; i < nCnt; i++)
1251     {
1252       strcpy (psz, pModule[i]);
1253       psz += strlen (psz) + 1;
1254     }
1255   return nCnt;
1256 }
1257 
1258 
1259 //
1260 // This function is rewritten by sang cho
1261 //
1262 //
1263 /* get import module function names separated by null terminators, return function count */
1264 int WINAPI
1265 GetImportFunctionNamesByModule (
1266 				 LPVOID lpFile,
1267 				 char *pszModule,
1268 				 char **pszFunctions)
1269 {
1270   PIMAGE_IMPORT_MODULE_DIRECTORY pid = (PIMAGE_IMPORT_MODULE_DIRECTORY)
1271   ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
1272   //
1273   // sometimes there may be no section for idata or edata
1274   // instead rdata or data section may contain these sections ..
1275   // or even module names or function names are in different section.
1276   // so that's why we need to get actual address each time.
1277   //         ...................sang cho..................
1278   //
1279   //PIMAGE_SECTION_HEADER           psh = (PIMAGE_SECTION_HEADER)
1280   //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
1281   //DWORD                  dwBase;
1282   int nCnt = 0, nSize = 0;
1283   int nnid = 0;
1284   int mnlength, i;
1285   DWORD dwFunctionName;
1286   DWORD dwFunctionAddress;
1287   char name[128];
1288   char buff[256];		// enough for any string ??
1289 
1290   char *psz;
1291   DWORD *pdw;
1292 
1293   //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
1294 
1295   /* find module's pid */
1296   while (pid->dwRVAModuleName &&
1297 	 strcmp (pszModule, (char *) GetActualAddress (lpFile, pid->dwRVAModuleName)))
1298     pid++;
1299 
1300   /* exit if the module is not found */
1301   if (!pid->dwRVAModuleName)
1302     return 0;
1303 
1304   // I am doing this to get rid of .dll from module name
1305   strcpy (name, pszModule);
1306   mnlength = strlen (pszModule);
1307   for (i = 0; i < mnlength; i++)
1308     if (name[i] == '.')
1309       break;
1310   name[i] = 0;
1311   mnlength = i;
1312 
1313   /* count number of function names and length of strings */
1314   dwFunctionName = pid->dwRVAFunctionNameList;
1315 
1316   // IMAGE_IMPORT_BY_NAME OR IMAGE_THUNK_DATA
1317   // modified by Sang Cho
1318   while (dwFunctionName &&
1319 	 *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName)))
1320     {
1321       if ((*pdw) & 0x80000000)
1322 	nSize += mnlength + 10 + 1 + 6;
1323       else
1324 	nSize += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1 + 6;
1325       dwFunctionName += 4;
1326       nCnt++;
1327     }
1328 
1329   /* allocate memory  for function names */
1330   *pszFunctions = (char *) calloc (nSize, 1);
1331   psz = *pszFunctions;
1332 
1333   //
1334   // I modified this part to store function address (4 bytes),
1335   //                               ord number (2 bytes),
1336   //                                                      and      name strings (which was there originally)
1337   // so that's why there are 6 more bytes...... +6,  or +4 and +2 etc.
1338   // these informations are used where they are needed.
1339   //                      ...........sang cho..................
1340   //
1341   /* copy function names to mempry pointer */
1342   dwFunctionName = pid->dwRVAFunctionNameList;
1343   dwFunctionAddress = pid->dwRVAFunctionAddressList;
1344   while (dwFunctionName &&
1345 	 *(pdw = (DWORD *) GetActualAddress (lpFile, dwFunctionName)))
1346     {
1347       if ((*pdw) & 0x80000000)
1348 	{
1349 	  *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress));
1350 	  psz += 4;
1351 	  *(short *) psz = *(short *) pdw;
1352 	  psz += 2;
1353 	  sprintf (buff, "%s:NoName%04d", name, nnid++);
1354 	  strcpy (psz, buff);
1355 	  psz += strlen (buff) + 1;
1356 	}
1357       else
1358 	{
1359 	  *(int *) psz = (int) (*(DWORD *) GetActualAddress (lpFile, dwFunctionAddress));
1360 	  psz += 4;
1361 	  *(short *) psz = (*(short *) GetActualAddress (lpFile, *pdw));
1362 	  psz += 2;
1363 	  strcpy (psz, (char *) GetActualAddress (lpFile, *pdw + 2));
1364 	  psz += strlen ((char *) GetActualAddress (lpFile, *pdw + 2)) + 1;
1365 	}
1366       dwFunctionName += 4;
1367       dwFunctionAddress += 4;
1368     }
1369 
1370   return nCnt;
1371 }
1372 
1373 
1374 
1375 
1376 //
1377 // This function is written by sang cho
1378 //                                                         October 6, 1997
1379 //
1380 /* get numerically expressed string length */
1381 int WINAPI
1382 GetStringLength (
1383 		  char *psz)
1384 {
1385   if (!isdigit (*psz))
1386     return 0;
1387   if (isdigit (*(psz + 1)))
1388     return (*psz - '0') * 10 + *(psz + 1) - '0';
1389   else
1390     return *psz - '0';
1391 }
1392 
1393 
1394 
1395 
1396 //
1397 // This function is written by sang cho
1398 //                                                         October 12, 1997
1399 //
1400 
1401 /* translate parameter part of condensed name */
1402 void WINAPI
1403 GetPreviousParamString (
1404 			 char *xpin,	// read-only source
1405 			  char *xpout)	// translated result
1406  {
1407   int n = 0;
1408   char *pin, *pout;
1409 
1410   pin = xpin;
1411   pout = xpout;
1412 
1413   pin--;
1414   if (*pin == ',')
1415     pin--;
1416   else
1417     {
1418       printf ("\n **error PreviousParamString1 char = %c", *pin);
1419       exit (0);
1420     }
1421 
1422   while (*pin)
1423     {
1424       if (*pin == '>')
1425 	n++;
1426       else if (*pin == '<')
1427 	n--;
1428       else if (*pin == ')')
1429 	n++;
1430 
1431       if (n > 0)
1432 	{
1433 	  if (*pin == '(')
1434 	    n--;
1435 	}
1436       else if (strchr (",(", *pin))
1437 	break;
1438       pin--;
1439     }
1440 
1441   //printf("\n ----- %s", pin);
1442   if (strchr (",(", *pin))
1443     {
1444       pin++;
1445     }				// printf("\n %s", pin); }
1446 
1447   else
1448     {
1449       printf ("\n **error PreviousParamString2");
1450       exit (0);
1451     }
1452 
1453   n = xpin - pin - 1;
1454   strncpy (pout, pin, n);
1455   *(pout + n) = 0;
1456 }
1457 
1458 
1459 
1460 
1461 //
1462 // This function is written by sang cho
1463 //                                                         October 10, 1997
1464 //
1465 
1466 /* translate parameter part of condensed name */
1467 void WINAPI
1468 TranslateParameters (
1469 		      char **ppin,	// read-only source
1470 		       char **ppout,	// translated result
1471 		       char **pps)	// parameter stack
1472  {
1473   int i, n;
1474   char c;
1475   char name[128];
1476   char *pin, *pout, *ps;
1477 
1478   //printf(" %c ", **in);
1479   pin = *ppin;
1480   pout = *ppout;
1481   ps = *pps;
1482   c = *pin;
1483   switch (c)
1484     {
1485       // types processing
1486     case 'b':
1487       strcpy (pout, "byte");
1488       pout += 4;
1489       pin++;
1490       break;
1491     case 'c':
1492       strcpy (pout, "char");
1493       pout += 4;
1494       pin++;
1495       break;
1496     case 'd':
1497       strcpy (pout, "double");
1498       pout += 6;
1499       pin++;
1500       break;
1501     case 'f':
1502       strcpy (pout, "float");
1503       pout += 5;
1504       pin++;
1505       break;
1506     case 'g':
1507       strcpy (pout, "long double");
1508       pout += 11;
1509       pin++;
1510       break;
1511     case 'i':
1512       strcpy (pout, "int");
1513       pout += 3;
1514       pin++;
1515       break;
1516     case 'l':
1517       strcpy (pout, "long");
1518       pout += 4;
1519       pin++;
1520       break;
1521     case 's':
1522       strcpy (pout, "short");
1523       pout += 5;
1524       pin++;
1525       break;
1526     case 'v':
1527       strcpy (pout, "void");
1528       pout += 4;
1529       pin++;
1530       break;
1531       // postfix processing
1532     case 'M':
1533     case 'p':
1534       if (*(pin + 1) == 'p')
1535 	{
1536 	  *ps++ = 'p';
1537 	  pin += 2;
1538 	}
1539       else
1540 	{
1541 	  *ps++ = '*';
1542 	  pin++;
1543 	}
1544       *ppin = pin;
1545       *ppout = pout;
1546       *pps = ps;
1547       return;
1548     case 'q':
1549       *pout++ = '(';
1550       pin++;
1551       *ps++ = 'q';
1552       *ppin = pin;
1553       *ppout = pout;
1554       *pps = ps;
1555       return;
1556     case 'r':
1557       if (*(pin + 1) == 'p')
1558 	{
1559 	  *ps++ = 'r';
1560 	  pin += 2;
1561 	}
1562       else
1563 	{
1564 	  *ps++ = '&';
1565 	  pin++;
1566 	}
1567       *ppin = pin;
1568       *ppout = pout;
1569       *pps = ps;
1570       return;
1571       // repeat processing
1572     case 't':
1573       if (isdigit (*(pin + 1)))
1574 	{
1575 	  n = *(pin + 1) - '0';
1576 	  pin++;
1577 	  pin++;
1578 	  GetPreviousParamString (pout, name);
1579 	  strcpy (pout, name);
1580 	  pout += strlen (name);
1581 	  for (i = 1; i < n; i++)
1582 	    {
1583 	      *pout++ = ',';
1584 	      strcpy (pout, name);
1585 	      pout += strlen (name);
1586 	    }
1587 	}
1588       else
1589 	pin++;
1590       break;
1591       // prefix processing
1592     case 'u':
1593       strcpy (pout, "u");
1594       pout += 1;
1595       pin++;
1596       *ppin = pin;
1597       *ppout = pout;
1598       *pps = ps;
1599       return;
1600     case 'x':
1601       strcpy (pout, "const ");
1602       pout += 6;
1603       pin++;
1604       *ppin = pin;
1605       *ppout = pout;
1606       *pps = ps;
1607       return;
1608     case 'z':
1609       strcpy (pout, "static ");
1610       pout += 7;
1611       pin++;
1612       *ppin = pin;
1613       *ppout = pout;
1614       *pps = ps;
1615       return;
1616     default:
1617       strcpy (pout, "!1!");
1618       pout += 3;
1619       *pout++ = *pin++;
1620       *ppin = pin;
1621       *ppout = pout;
1622       *pps = ps;
1623       return;
1624     }
1625   // need to process postfix finally
1626   c = *(ps - 1);
1627   if (strchr ("tqx", c))
1628     {
1629       if (*(pin) && !strchr ("@$%", *(pin)))
1630 	*pout++ = ',';
1631       *ppin = pin;
1632       *ppout = pout;
1633       *pps = ps;
1634       return;
1635     }
1636   switch (c)
1637     {
1638     case 'r':
1639       strcpy (pout, "*&");
1640       pout += 2;
1641       ps--;
1642       break;
1643     case 'p':
1644       strcpy (pout, "**");
1645       pout += 2;
1646       ps--;
1647       break;
1648     case '&':
1649       strcpy (pout, "&");
1650       pout += 1;
1651       ps--;
1652       break;
1653     case '*':
1654       strcpy (pout, "*");
1655       pout += 1;
1656       ps--;
1657       break;
1658     default:
1659       strcpy (pout, "!2!");
1660       pout += 3;
1661       ps--;
1662       break;
1663     }
1664   if (*(pin) && !strchr ("@$%", *(pin)))
1665     *pout++ = ',';
1666   *ppin = pin;
1667   *ppout = pout;
1668   *pps = ps;
1669 }
1670 
1671 
1672 //
1673 // This function is written by sang cho
1674 //                                                         October 11, 1997
1675 //
1676 
1677 /* translate parameter part of condensed name */
1678 BOOL WINAPI
1679 StringExpands (
1680 		char **ppin,	// read-only source
1681 		 char **ppout,	// translated result
1682 		 char **pps,	// parameter stack
1683 		 Str_P * pcstr)	// currently stored string
1684  {
1685 //      int         n;
1686   //      char        c;
1687   char *pin, *pout, *ps;
1688   Str_P c_str;
1689   BOOL stringMode = TRUE;
1690 
1691   pin = *ppin;
1692   pout = *ppout;
1693   ps = *pps;
1694   c_str = *pcstr;
1695 
1696   if (strncmp (pin, "bctr", 4) == 0)
1697     {
1698       strncpy (pout, c_str.pos, c_str.length);
1699       pout += c_str.length;
1700       pin += 4;
1701     }
1702   else if (strncmp (pin, "bdtr", 4) == 0)
1703     {
1704       *pout++ = '~';
1705       strncpy (pout, c_str.pos, c_str.length);
1706       pout += c_str.length;
1707       pin += 4;
1708     }
1709   else if (*pin == 'o')
1710     {
1711       strcpy (pout, "const ");
1712       pout += 6;
1713       pin++;
1714       stringMode = FALSE;
1715     }
1716   else if (*pin == 'q')
1717     {
1718       *pout++ = '(';
1719       pin++;
1720       *ps++ = 'q';
1721       stringMode = FALSE;
1722     }
1723   else if (*pin == 't')
1724     {
1725       //if (*(ps-1) == 't') { *pout++ = ','; pin++; }       // this also got me...
1726       //else                                                                                          october 12  .. sang
1727       {
1728 	*pout++ = '<';
1729 	pin++;
1730 	*ps++ = 't';
1731       }
1732       stringMode = FALSE;
1733     }
1734   else if (strncmp (pin, "xq", 2) == 0)
1735     {
1736       *pout++ = '(';
1737       pin += 2;
1738       *ps++ = 'x';
1739       *ps++ = 'q';
1740       stringMode = FALSE;
1741     }
1742   else if (strncmp (pin, "bcall", 5) == 0)
1743     {
1744       strcpy (pout, "operator ()");
1745       pout += 11;
1746       pin += 5;
1747     }
1748   else if (strncmp (pin, "bsubs", 5) == 0)
1749     {
1750       strcpy (pout, "operator []");
1751       pout += 11;
1752       pin += 5;
1753     }
1754   else if (strncmp (pin, "bnwa", 4) == 0)
1755     {
1756       strcpy (pout, "operator new[]");
1757       pout += 14;
1758       pin += 4;
1759     }
1760   else if (strncmp (pin, "bdla", 4) == 0)
1761     {
1762       strcpy (pout, "operator delete[]");
1763       pout += 17;
1764       pin += 4;
1765     }
1766   else if (strncmp (pin, "bnew", 4) == 0)
1767     {
1768       strcpy (pout, "operator new");
1769       pout += 12;
1770       pin += 4;
1771     }
1772   else if (strncmp (pin, "bdele", 5) == 0)
1773     {
1774       strcpy (pout, "operator delete");
1775       pout += 15;
1776       pin += 5;
1777     }
1778   else if (strncmp (pin, "blsh", 4) == 0)
1779     {
1780       strcpy (pout, "operator <<");
1781       pout += 11;
1782       pin += 4;
1783     }
1784   else if (strncmp (pin, "brsh", 4) == 0)
1785     {
1786       strcpy (pout, "operator >>");
1787       pout += 11;
1788       pin += 4;
1789     }
1790   else if (strncmp (pin, "binc", 4) == 0)
1791     {
1792       strcpy (pout, "operator ++");
1793       pout += 11;
1794       pin += 4;
1795     }
1796   else if (strncmp (pin, "bdec", 4) == 0)
1797     {
1798       strcpy (pout, "operator --");
1799       pout += 11;
1800       pin += 4;
1801     }
1802   else if (strncmp (pin, "badd", 4) == 0)
1803     {
1804       strcpy (pout, "operator +");
1805       pout += 10;
1806       pin += 4;
1807     }
1808   else if (strncmp (pin, "brplu", 5) == 0)
1809     {
1810       strcpy (pout, "operator +=");
1811       pout += 11;
1812       pin += 5;
1813     }
1814   else if (strncmp (pin, "bdiv", 4) == 0)
1815     {
1816       strcpy (pout, "operator /");
1817       pout += 10;
1818       pin += 4;
1819     }
1820   else if (strncmp (pin, "brdiv", 5) == 0)
1821     {
1822       strcpy (pout, "operator /=");
1823       pout += 11;
1824       pin += 5;
1825     }
1826   else if (strncmp (pin, "bmul", 4) == 0)
1827     {
1828       strcpy (pout, "operator *");
1829       pout += 10;
1830       pin += 4;
1831     }
1832   else if (strncmp (pin, "brmul", 5) == 0)
1833     {
1834       strcpy (pout, "operator *=");
1835       pout += 11;
1836       pin += 5;
1837     }
1838   else if (strncmp (pin, "basg", 4) == 0)
1839     {
1840       strcpy (pout, "operator =");
1841       pout += 10;
1842       pin += 4;
1843     }
1844   else if (strncmp (pin, "beql", 4) == 0)
1845     {
1846       strcpy (pout, "operator ==");
1847       pout += 11;
1848       pin += 4;
1849     }
1850   else if (strncmp (pin, "bneq", 4) == 0)
1851     {
1852       strcpy (pout, "operator !=");
1853       pout += 11;
1854       pin += 4;
1855     }
1856   else if (strncmp (pin, "bor", 3) == 0)
1857     {
1858       strcpy (pout, "operator |");
1859       pout += 10;
1860       pin += 3;
1861     }
1862   else if (strncmp (pin, "bror", 4) == 0)
1863     {
1864       strcpy (pout, "operator |=");
1865       pout += 11;
1866       pin += 4;
1867     }
1868   else if (strncmp (pin, "bcmp", 4) == 0)
1869     {
1870       strcpy (pout, "operator ~");
1871       pout += 10;
1872       pin += 4;
1873     }
1874   else if (strncmp (pin, "bnot", 4) == 0)
1875     {
1876       strcpy (pout, "operator !");
1877       pout += 10;
1878       pin += 4;
1879     }
1880   else if (strncmp (pin, "band", 4) == 0)
1881     {
1882       strcpy (pout, "operator &");
1883       pout += 10;
1884       pin += 4;
1885     }
1886   else if (strncmp (pin, "brand", 5) == 0)
1887     {
1888       strcpy (pout, "operator &=");
1889       pout += 11;
1890       pin += 5;
1891     }
1892   else if (strncmp (pin, "bxor", 4) == 0)
1893     {
1894       strcpy (pout, "operator ^");
1895       pout += 10;
1896       pin += 4;
1897     }
1898   else if (strncmp (pin, "brxor", 5) == 0)
1899     {
1900       strcpy (pout, "operator ^=");
1901       pout += 11;
1902       pin += 5;
1903     }
1904   else
1905     {
1906       strcpy (pout, "!$$$!");
1907       pout += 5;
1908     }
1909   *ppin = pin;
1910   *ppout = pout;
1911   *pps = ps;
1912   return stringMode;
1913 }				// end of '$' processing
1914 
1915 
1916 
1917 //----------------------------------------------------------------------
1918 // structure to store string tokens
1919 //----------------------------------------------------------------------
1920 //typedef struct _Str_P {
1921 //    char    flag;               // string_flag '@' or '%' or '#'
1922 //    char    *pos;               // starting postion of string
1923 //    int     length;     // length of string
1924 //      BOOL    wasString;    // if it were stringMode or not
1925 //} Str_P;
1926 //----------------------------------------------------------------------
1927 //
1928 // I think I knocked it down finally. But who knows?
1929 //                            october 12, 1997 ... sang
1930 //
1931 // well I have to rewrite whole part of TranslateFunctionName..
1932 // this time I am a little bit more experienced than 5 days ago.
1933 // or am i??? anyway i use stacks instead of recurcive calls
1934 // and i hope this will take care of every symptoms i have experienced..
1935 //                                                        october 10, 1997 .... sang
1936 // It took a lot of time for me to figure out what is all about....
1937 // but still some prefixes like z (static)
1938 //     -- or some types like b (byte) ,g (long double) ,s (short) --
1939 //         -- or postfix  like M ( * )
1940 //     -- or $or ( & ) which is pretty wierd.         .. added.. october 12
1941 //     -- also $t business is quite tricky too. (templates)
1942 //             there may be a lot of things undiscovered yet....
1943 // I am not so sure my interpretation is correct or not
1944 // If I am wrong please let me know.
1945 //                             october 8, 1997 .... sang
1946 //
1947 //
1948 // This function is written by sang cho
1949 //                                                         October 5, 1997
1950 //
1951 /* translate condesed import function name */
1952 char * WINAPI
1953 TranslateFunctionName (
1954 			char *psz)
1955 {
1956 
1957 
1958   int i, /*j,*/ n;
1959   char c = 0;
1960   char cc;
1961 
1962   static char buff[512];	// result of translation
1963 
1964   int is = 0;
1965   char pStack[32];		// parameter processing stack
1966 
1967   Str_P sStack[32];		// String processing stack
1968 
1969   Str_P tok;			// String token
1970 
1971   Str_P c_str;			// current string
1972 
1973   int iend = 0;
1974   char *endTab[8];		// end of string position check
1975 
1976   char *ps;
1977   char *pin, *pout;
1978   BOOL stringMode = TRUE;
1979 
1980   if (*psz != '@')
1981     return psz;
1982   pin = psz;
1983   pout = buff;
1984   ps = pStack;
1985 
1986   //................................................................
1987   // serious users may need to run the following code.
1988   // so I may need to include some flag options...
1989   // If you want to know about how translation is done,
1990   // you can just revive following line and you can see it.
1991   //                                                 october 6, 1997 ... sang cho
1992   //printf ("\n................................... %s", psz); // for debugging...
1993 
1994   //pa = pb = pout;
1995   pin++;
1996   tok.flag = 'A';
1997   tok.pos = pout;
1998   tok.length = 0;
1999   tok.wasString = stringMode;
2000   sStack[is++] = tok;		// initialize sStack with dummy marker
2001 
2002   while (*pin)
2003     {
2004       while (*pin)
2005 	{
2006 	  c = *pin;
2007 
2008 	  //---------------------------------------------
2009 	  // check for the end of number specified string
2010 	  //---------------------------------------------
2011 
2012 	  if (iend > 0)
2013 	    {
2014 	      for (i = 0; i < iend; i++)
2015 		if (pin == endTab[i])
2016 		  break;
2017 	      if (i < iend)
2018 		{
2019 		  // move the end of endTab to ith position
2020 		  endTab[i] = endTab[iend - 1];
2021 		  iend--;
2022 
2023 		  // get top of the string stack
2024 		  tok = sStack[is - 1];
2025 
2026 		  // I am expecting '#' token from stack
2027 		  if (tok.flag != '#')
2028 
2029 		    {
2030 		      printf ("\n**some serious error1** %c is = %d char = %c",
2031 			      tok.flag, is, *pin);
2032 		      exit (0);
2033 		    }
2034 
2035 		  // pop '#' token  I am happy now.
2036 		  else
2037 		    {		//if (c)
2038 		      //printf("\n pop # token ... current char = %c", c);
2039 		      //else printf("\n pop percent token..next char = NULL");
2040 
2041 		      is--;
2042 		    }
2043 
2044 		  stringMode = tok.wasString;
2045 
2046 		  if (!stringMode)
2047 		    {
2048 		      // need to process postfix finally
2049 		      cc = *(ps - 1);
2050 		      if (strchr ("qtx", cc))
2051 			{
2052 			  if (!strchr ("@$%", c))
2053 			    *pout++ = ',';
2054 			}
2055 		      else
2056 			{
2057 			  switch (cc)
2058 			    {
2059 			    case 'r':
2060 			      strcpy (pout, "*&");
2061 			      pout += 2;
2062 			      ps--;
2063 			      break;
2064 			    case 'p':
2065 			      strcpy (pout, "**");
2066 			      pout += 2;
2067 			      ps--;
2068 			      break;
2069 			    case '&':
2070 			      strcpy (pout, "&");
2071 			      pout += 1;
2072 			      ps--;
2073 			      break;
2074 			    case '*':
2075 			      strcpy (pout, "*");
2076 			      pout += 1;
2077 			      ps--;
2078 			      break;
2079 			    default:
2080 			      strcpy (pout, "!3!");
2081 			      pout += 3;
2082 			      ps--;
2083 			      break;
2084 			    }
2085 			  if (!strchr ("@$%", c))
2086 			    *pout++ = ',';
2087 			}
2088 		    }
2089 		  // string mode restored...
2090 		  else;
2091 		}
2092 	      else;		// do nothing..
2093 
2094 	    }
2095 
2096 	  //------------------------------------------------
2097 	  // special control symbol processing:
2098 	  //------------------------------------------------
2099 
2100 	  if (strchr ("@$%", c))
2101 	    break;
2102 
2103 	  //---------------------------------------------------------------
2104 	  // string part processing : no '$' met yet
2105 	  //                       or inside of '%' block
2106 	  //                       or inside of '#' block (numbered string)
2107 	  //---------------------------------------------------------------
2108 
2109 	  else if (stringMode)
2110 	    *pout++ = *pin++;
2111 	  //else if (is > 1)         *pout++ = *pin++;
2112 
2113 	  //------------------------------------------------
2114 	  // parameter part processing: '$' met
2115 	  //------------------------------------------------
2116 
2117 	  else			// parameter processing
2118 
2119 	    {
2120 	      if (!isdigit (c))
2121 		TranslateParameters (&pin, &pout, &ps);
2122 	      else		// number specified string processing
2123 
2124 		{
2125 		  n = GetStringLength (pin);
2126 		  if (n < 10)
2127 		    pin++;
2128 		  else
2129 		    pin += 2;
2130 
2131 		  // push '#' token
2132 		  //if (*pin)
2133 		  //printf("\n push # token .. char = %c", *pin);
2134 		  //else printf("\n push percent token..next char = NULL");
2135 		  tok.flag = '#';
2136 		  tok.pos = pout;
2137 		  tok.length = 0;
2138 		  tok.wasString = stringMode;
2139 		  sStack[is++] = tok;
2140 
2141 		  // mark end of input string
2142 		  endTab[iend++] = pin + n;
2143 		  stringMode = TRUE;
2144 		}
2145 	    }
2146 	}			// end of inner while loop
2147       //
2148       // beginning of new string or end of string ( quotation mark )
2149       //
2150 
2151       if (c == '%')
2152 	{
2153 	  pin++;		// anyway we have to proceed...
2154 
2155 	  tok = sStack[is - 1];	// get top of the sStack
2156 
2157 	  if (tok.flag == '%')
2158 	    {
2159 	      // pop '%' token and set c_str
2160 	      //if (*pin)
2161 	      //printf("\n pop percent token..next char = %c", *pin);
2162 	      //else printf("\n pop percent token..next char = NULL");
2163 	      is--;
2164 	      c_str = tok;
2165 	      c_str.length = pout - c_str.pos;
2166 	      if (*(ps - 1) == 't')
2167 		{
2168 		  *pout++ = '>';
2169 		  ps--;
2170 		  stringMode = tok.wasString;
2171 		}
2172 	      else
2173 		{
2174 		  printf ("\n**some string error3** stack = %c", *(ps - 1));
2175 		  exit (0);
2176 		}
2177 	    }
2178 	  else if (tok.flag == 'A' || tok.flag == '#')
2179 	    {
2180 	      // push '%' token
2181 	      //if (*pin)
2182 	      //printf("\n push percent token..next char = %c", *pin);
2183 	      //else printf("\n push percent token..next char = NULL");
2184 	      tok.flag = '%';
2185 	      tok.pos = pout;
2186 	      tok.length = 0;
2187 	      tok.wasString = stringMode;
2188 	      sStack[is++] = tok;
2189 	    }
2190 	  else
2191 	    {
2192 	      printf ("\n**some string error5**");
2193 	      exit (0);
2194 	    }
2195 	}
2196       //
2197       // sometimes we need string to use as constructor name or destructor name
2198       //
2199       else if (c == '@')	// get string from previous marker  upto here.
2200 
2201 	{
2202 	  pin++;
2203 	  tok = sStack[is - 1];
2204 	  c_str.flag = 'S';
2205 	  c_str.pos = tok.pos;
2206 	  c_str.length = pout - tok.pos;
2207 	  c_str.wasString = stringMode;
2208 	  *pout++ = ':';
2209 	  *pout++ = ':';
2210 	}
2211       //
2212       // we need to take care of parameter control sequence
2213       //
2214       else if (c == '$')	// need to precess template or parameter part
2215 
2216 	{
2217 	  pin++;
2218 	  if (stringMode)
2219 	    stringMode = StringExpands (&pin, &pout, &ps, &c_str);
2220 	  else
2221 	    {			// template parameter mode I guess  "$t"
2222 
2223 	      if (is > 1)
2224 		{
2225 		  if (*pin == 't')
2226 		    pin++;
2227 		  else
2228 		    {
2229 		      printf ("\nMYGOODNESS1 %c", *pin);
2230 		      exit (0);
2231 		    }
2232 		  //ps--;
2233 		  //if (*ps == 't') *pout++ = '>';
2234 		  //else { printf("\nMYGOODNESS2"); exit(0);}
2235 		  *pout++ = ',';	//pin++; ..this almost blowed me....
2236 
2237 		}
2238 	      // real parameter mode I guess
2239 	      // unexpected case is found ... humm what can I do...
2240 	      else
2241 		{
2242 		  // this is newly found twist.. it really hurts.
2243 		  if (ps <= pStack)
2244 		    {
2245 		      if (*pin == 'q')
2246 			{
2247 			  *ps++ = 'q';
2248 			  *pout++ = '(';
2249 			  pin++;
2250 			}
2251 		      else
2252 			{
2253 			  printf ("\n** I GIVEUP ***");
2254 			  exit (0);
2255 			}
2256 		      continue;
2257 		    }
2258 		  ps--;
2259 		  while (*ps != 'q')
2260 		    {
2261 		      if (*ps == '*')
2262 			*pout++ = '*';
2263 		      else if (*ps == '&')
2264 			*pout++ = '&';
2265 		      else if (*ps == 'p')
2266 			{
2267 			  *pout++ = '*';
2268 			  *pout++ = '*';
2269 			}
2270 		      else if (*ps == 'r')
2271 			{
2272 			  *pout++ = '*';
2273 			  *pout++ = '&';
2274 			}
2275 		      else
2276 			{
2277 			  printf ("\n*** SOMETHING IS WRONG1*** char= %c", *pin);
2278 			  exit (0);
2279 			}
2280 		      ps--;
2281 		    }
2282 		  *pout++ = ')';
2283 		  ps--;
2284 		  while (*ps != 'q')
2285 		    {
2286 		      if (*ps == '*')
2287 			*pout++ = '*';
2288 		      else if (*ps == '&')
2289 			*pout++ = '&';
2290 		      else if (*ps == 'p')
2291 			{
2292 			  *pout++ = '*';
2293 			  *pout++ = '*';
2294 			}
2295 		      else if (*ps == 'r')
2296 			{
2297 			  *pout++ = '*';
2298 			  *pout++ = '&';
2299 			}
2300 		      else
2301 			{
2302 			  printf ("\n*** SOMETHING IS WRONG2***");
2303 			  exit (0);
2304 			}
2305 		      ps--;
2306 		    }
2307 		  ps++;
2308 		  *pout++ = ',';
2309 		}
2310 	    }
2311 	}			// end of '$' processing
2312 
2313     }				// end of outer while loop
2314   //
2315   // need to process remaining parameter stack
2316   //
2317 
2318   while (ps > pStack)
2319     {
2320       ps--;
2321       switch (*ps)
2322 	{
2323 	case 't':
2324 	  *pout++ = '>';
2325 	  break;
2326 	case 'q':
2327 	  *pout++ = ')';
2328 	  break;
2329 	case 'x':
2330 	  strcpy (pout, " const");
2331 	  pout += 6;
2332 	  break;
2333 	case 'r':
2334 	  strcpy (pout, "*&");
2335 	  pout += 2;
2336 	  break;
2337 	case 'p':
2338 	  strcpy (pout, "**");
2339 	  pout += 2;
2340 	  break;
2341 	case '&':
2342 	  *pout++ = '&';
2343 	  break;
2344 	case '*':
2345 	  *pout++ = '*';
2346 	  break;
2347 	default:
2348 	  strcpy (pout, "!4!");
2349 	  pout += 3;
2350 	  *pout++ = *ps;
2351 	}
2352     }
2353   *pout = 0;
2354   return buff;
2355 }
2356 
2357 
2358 
2359 //
2360 // This function is written by sang cho
2361 //
2362 //
2363 /* get exported function names separated by null terminators, return count of functions */
2364 int WINAPI
2365 GetExportFunctionNames (
2366 			 LPVOID lpFile,
2367 			 char **pszFunctions)
2368 {
2369   //PIMAGE_SECTION_HEADER      psh;
2370   PIMAGE_EXPORT_DIRECTORY ped;
2371   //DWORD                      dwBase;
2372   DWORD imageBase;		//===========================
2373 
2374   char *pfns[8192] =
2375   {NULL,};			// maximum number of functions
2376   //=============================
2377 
2378   char buff[256];		// enough for any string ??
2379 
2380   char *psz = NULL;			//===============================
2381 
2382   DWORD *pdwAddress;
2383   DWORD *pdw1;
2384   DWORD *pdwNames;
2385   WORD *pwOrd;
2386   int i, nCnt = 0, ntmp = 0;
2387   int enid = 0, ordBase = 1;	// usally ordBase is 1....
2388 
2389   int enames = 0;
2390 
2391   /* get section header and pointer to data directory for .edata section */
2392   ped = (PIMAGE_EXPORT_DIRECTORY)
2393     ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT);
2394 
2395   if (ped == NULL)
2396     return 0;
2397 
2398   //
2399   // sometimes there may be no section for idata or edata
2400   // instead rdata or data section may contain these sections ..
2401   // or even module names or function names are in different section.
2402   // so that's why we need to get actual address each time.
2403   //         ...................sang cho..................
2404   //
2405   //psh = (PIMAGE_SECTION_HEADER)
2406   //ImageDirectorySection(lpFile, IMAGE_DIRECTORY_ENTRY_EXPORT);
2407 
2408   //if (psh == NULL) return 0;
2409 
2410   //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
2411 
2412 
2413   /* determine the offset of the export function names */
2414 
2415   pdwAddress = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfFunctions);
2416 
2417   imageBase = (DWORD) GetImageBase (lpFile);
2418 
2419   ordBase = ped->Base;
2420 
2421   if (ped->NumberOfNames > 0)
2422     {
2423       pdwNames = (DWORD *)
2424 	GetActualAddress (lpFile, (DWORD) ped->AddressOfNames);
2425       pwOrd = (WORD *)
2426 	GetActualAddress (lpFile, (DWORD) ped->AddressOfNameOrdinals);
2427       pdw1 = pdwAddress;
2428 
2429       /* figure out how much memory to allocate for all strings */
2430       for (i = 0; i < (int) ped->NumberOfNames; i++)
2431 	{
2432 	  nCnt += strlen ((char *)
2433 		    GetActualAddress (lpFile, *(DWORD *) pdwNames)) + 1 + 6;
2434 	  pdwNames++;
2435 	}
2436       // get the number of unnamed functions
2437       for (i = 0; i < (int) ped->NumberOfFunctions; i++)
2438 	if (*pdw1++)
2439 	  ntmp++;
2440       // add memory required to show unnamed functions.
2441       if (ntmp > (int) ped->NumberOfNames)
2442 	nCnt += 18 * (ntmp - (int) ped->NumberOfNames);
2443 
2444       /* allocate memory  for function names */
2445 
2446       *pszFunctions = (char *) calloc (nCnt, 1);
2447       pdwNames = (DWORD *) GetActualAddress (lpFile, (DWORD) ped->AddressOfNames);
2448 
2449       /* copy string pointer to buffer */
2450 
2451       for (i = 0; i < (int) ped->NumberOfNames; i++)
2452 	{
2453 	  pfns[(int) (*pwOrd) + ordBase] =
2454 	    (char *) GetActualAddress (lpFile, *(DWORD *) pdwNames);
2455 	  pdwNames++;
2456 	  pwOrd++;
2457 	}
2458 
2459       psz = *pszFunctions;
2460     }
2461 
2462   for (i = ordBase; i < (int) ped->NumberOfFunctions + ordBase; i++)
2463     {
2464       if (*pdwAddress > 0)
2465 	{
2466 	  *(DWORD *) psz = imageBase + *pdwAddress;
2467 	  psz += 4;
2468 	  *(WORD *) psz = (WORD) (i);
2469 	  psz += 2;
2470 	  if (pfns[i])
2471 	    {
2472 	      strcpy (psz, pfns[i]);
2473 	      psz += strlen (psz) + 1;
2474 	    }
2475 	  else
2476 	    {
2477 	      sprintf (buff, "ExpFn%04d()", enid++);
2478 	      strcpy (psz, buff);
2479 	      psz += 12;
2480 	    }
2481 	  enames++;
2482 	}
2483       pdwAddress++;
2484     }
2485 
2486   return enames;
2487 
2488 }
2489 
2490 
2491 /* determine the total number of resources in the section */
2492 int WINAPI
2493 GetNumberOfResources (
2494 		       LPVOID lpFile)
2495 {
2496   PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
2497   PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
2498   int nCnt = 0, i;
2499 
2500 
2501   /* get root directory of resource tree */
2502   if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
2503        (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
2504     return 0;
2505 
2506   /* set pointer to first resource type entry */
2507   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
2508 
2509   /* loop through all resource directory entry types */
2510   for (i = 0; i < prdRoot->NumberOfIdEntries; i++)
2511     {
2512       /* locate directory or each resource type */
2513       prdType = (PIMAGE_RESOURCE_DIRECTORY) ((int) prdRoot + (int) prde->OffsetToData);
2514 
2515       /* mask off most significant bit of the data offset */
2516       prdType = (PIMAGE_RESOURCE_DIRECTORY) ((DWORD) prdType ^ 0x80000000);
2517 
2518       /* increment count of name'd and ID'd resources in directory */
2519       nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
2520 
2521       /* increment to next entry */
2522       prde++;
2523     }
2524 
2525   return nCnt;
2526 }
2527 
2528 
2529 
2530 //
2531 // This function is rewritten by sang cho
2532 //
2533 //
2534 /* name each type of resource in the section */
2535 int WINAPI
2536 GetListOfResourceTypes (
2537 			 LPVOID lpFile,
2538 			 char **pszResTypes)
2539 {
2540   PIMAGE_RESOURCE_DIRECTORY prdRoot;
2541   PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
2542   char *pMem;
2543   char buff[32];
2544   int nCnt, i;
2545   DWORD prdeName;
2546 
2547 
2548   /* get root directory of resource tree */
2549   if ((prdRoot = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
2550        (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
2551     return 0;
2552 
2553   /* allocate enuff space  to cover all types */
2554   nCnt = prdRoot->NumberOfIdEntries * (MAXRESOURCENAME + 1);
2555   *pszResTypes = (char *) calloc (nCnt, 1);
2556   if ((pMem = *pszResTypes) == NULL)
2557     return 0;
2558 
2559   /* set pointer to first resource type entry */
2560   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ((DWORD) prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
2561 
2562   /* loop through all resource directory entry types */
2563   for (i = 0; i < prdRoot->NumberOfIdEntries; i++)
2564     {
2565       prdeName = prde->Name;
2566 
2567       //if (LoadString (hDll, prde->Name, pMem, MAXRESOURCENAME))
2568       //    pMem += strlen (pMem) + 1;
2569       //
2570       // modified by ...................................Sang Cho..
2571       // I can't user M/S provied funcitons here so I have to figure out
2572       // how to do above functions. But I can settle down with the following
2573       // code, which works pretty good for me.
2574       //
2575       if (prdeName == 1)
2576 	{
2577 	  strcpy (pMem, "RT_CURSOR");
2578 	  pMem += 10;
2579 	}
2580       else if (prdeName == 2)
2581 	{
2582 	  strcpy (pMem, "RT_BITMAP");
2583 	  pMem += 10;
2584 	}
2585       else if (prdeName == 3)
2586 	{
2587 	  strcpy (pMem, "RT_ICON  ");
2588 	  pMem += 10;
2589 	}
2590       else if (prdeName == 4)
2591 	{
2592 	  strcpy (pMem, "RT_MENU  ");
2593 	  pMem += 10;
2594 	}
2595       else if (prdeName == 5)
2596 	{
2597 	  strcpy (pMem, "RT_DIALOG");
2598 	  pMem += 10;
2599 	}
2600       else if (prdeName == 6)
2601 	{
2602 	  strcpy (pMem, "RT_STRING");
2603 	  pMem += 10;
2604 	}
2605       else if (prdeName == 7)
2606 	{
2607 	  strcpy (pMem, "RT_FONTDIR");
2608 	  pMem += 11;
2609 	}
2610       else if (prdeName == 8)
2611 	{
2612 	  strcpy (pMem, "RT_FONT  ");
2613 	  pMem += 10;
2614 	}
2615       else if (prdeName == 9)
2616 	{
2617 	  strcpy (pMem, "RT_ACCELERATORS");
2618 	  pMem += 16;
2619 	}
2620       else if (prdeName == 10)
2621 	{
2622 	  strcpy (pMem, "RT_RCDATA");
2623 	  pMem += 10;
2624 	}
2625       else if (prdeName == 11)
2626 	{
2627 	  strcpy (pMem, "RT_MESSAGETABLE");
2628 	  pMem += 16;
2629 	}
2630       else if (prdeName == 12)
2631 	{
2632 	  strcpy (pMem, "RT_GROUP_CURSOR");
2633 	  pMem += 16;
2634 	}
2635       else if (prdeName == 14)
2636 	{
2637 	  strcpy (pMem, "RT_GROUP_ICON  ");
2638 	  pMem += 16;
2639 	}
2640       else if (prdeName == 16)
2641 	{
2642 	  strcpy (pMem, "RT_VERSION");
2643 	  pMem += 11;
2644 	}
2645       else if (prdeName == 17)
2646 	{
2647 	  strcpy (pMem, "RT_DLGINCLUDE  ");
2648 	  pMem += 16;
2649 	}
2650       else if (prdeName == 19)
2651 	{
2652 	  strcpy (pMem, "RT_PLUGPLAY    ");
2653 	  pMem += 16;
2654 	}
2655       else if (prdeName == 20)
2656 	{
2657 	  strcpy (pMem, "RT_VXD   ");
2658 	  pMem += 10;
2659 	}
2660       else if (prdeName == 21)
2661 	{
2662 	  strcpy (pMem, "RT_ANICURSOR   ");
2663 	  pMem += 16;
2664 	}
2665       else if (prdeName == 22)
2666 	{
2667 	  strcpy (pMem, "RT_ANIICON");
2668 	  pMem += 11;
2669 	}
2670       else if (prdeName == 0x2002)
2671 	{
2672 	  strcpy (pMem, "RT_NEWBITMAP");
2673 	  pMem += 13;
2674 	}
2675       else if (prdeName == 0x2004)
2676 	{
2677 	  strcpy (pMem, "RT_NEWMENU");
2678 	  pMem += 11;
2679 	}
2680       else if (prdeName == 0x2005)
2681 	{
2682 	  strcpy (pMem, "RT_NEWDIALOG");
2683 	  pMem += 13;
2684 	}
2685       else if (prdeName == 0x7fff)
2686 	{
2687 	  strcpy (pMem, "RT_ERROR ");
2688 	  pMem += 10;
2689 	}
2690       else
2691 	{
2692 	  sprintf (buff, "RT_UNKNOWN:%08lX", prdeName);
2693 	  strcpy (pMem, buff);
2694 	  pMem += 20;
2695 	}
2696       prde++;
2697     }
2698 
2699   return prdRoot->NumberOfIdEntries;
2700 }
2701 
2702 
2703 
2704 //
2705 // This function is written by sang cho
2706 //                                                         October 12, 1997
2707 //
2708 /* copy menu information */
2709 void WINAPI
2710 StrangeMenuFill (
2711 		  char **psz,	// results
2712 		   WORD ** pMenu,	// read-only
2713 		   int size)
2714 {
2715   WORD *pwd;
2716   WORD *ptr, *pmax;
2717 
2718   pwd = *pMenu;
2719   pmax = (WORD *) ((DWORD) pwd + size);
2720   ptr = (WORD *) (*psz);
2721 
2722   while (pwd < pmax)
2723     {
2724       *ptr++ = *pwd++;
2725     }
2726   *psz = (char *) ptr;
2727   *pMenu = pwd;
2728 }
2729 
2730 
2731 
2732 //
2733 // This function is written by sang cho
2734 //                                                         October 1, 1997
2735 //
2736 /* obtain menu information */
2737 int WINAPI
2738 MenuScan (
2739 	   int *len,
2740 	   WORD ** pMenu)
2741 {
2742   //int num = 0;
2743   //int ndetails;
2744   WORD *pwd;
2745   WORD flag, flag1;
2746   WORD id, ispopup;
2747 
2748 
2749   pwd = *pMenu;
2750 
2751   flag = *pwd;			// so difficult to correctly code this so let's try this
2752 
2753   pwd++;
2754   (*len) += 2;			// flag store
2755 
2756   if ((flag & 0x0010) == 0)
2757     {
2758       ispopup = flag;
2759       id = *pwd;
2760       pwd++;
2761       (*len) += 2;		// id store
2762 
2763     }
2764   else
2765     {
2766       ispopup = flag;
2767     }
2768 
2769   while (*pwd)
2770     {
2771       (*len)++;
2772       pwd++;
2773     }
2774   (*len)++;			// name and null character
2775 
2776   pwd++;			// skip double null
2777 
2778   if ((flag & 0x0010) == 0)	// normal node: done
2779 
2780     {
2781       *pMenu = pwd;
2782       return (int) flag;
2783     }
2784   // popup node: need to go on...
2785   while (1)
2786     {
2787       *pMenu = pwd;
2788       flag1 = (WORD) MenuScan (len, pMenu);
2789       pwd = *pMenu;
2790       if (flag1 & 0x0080)
2791 	break;
2792     }
2793 //  fill # of details to num above
2794   //(*len) += 2;
2795   *pMenu = pwd;
2796   return flag;
2797 }
2798 
2799 
2800 //
2801 // This function is written by sang cho
2802 //                                                         October 2, 1997
2803 //
2804 /* copy menu information */
2805 int WINAPI
2806 MenuFill (
2807 	   char **psz,
2808 	   WORD ** pMenu)
2809 {
2810   //int num = 0;
2811   //int ndetails;
2812   char *ptr/*, *pTemp*/;
2813   WORD *pwd;
2814   WORD flag, flag1;
2815   WORD id/*, ispopup*/;
2816 
2817   ptr = *psz;
2818   pwd = *pMenu;
2819   //flag = (*(PIMAGE_POPUP_MENU_ITEM *)pwd)->fItemFlags;
2820   flag = *pwd;			// so difficult to correctly code this so let's try this
2821 
2822   pwd++;
2823   if ((flag & 0x0010) == 0)
2824     {
2825       *(WORD *) ptr = flag;	// flag store
2826 
2827       ptr += 2;
2828       *(WORD *) ptr = id = *pwd;	// id store
2829 
2830       ptr += 2;
2831       pwd++;
2832     }
2833   else
2834     {
2835       *(WORD *) ptr = flag;	// flag store
2836 
2837       ptr += 2;
2838     }
2839 
2840   while (*pwd)			// name extract
2841 
2842     {
2843       *ptr = *(char *) pwd;
2844       ptr++;
2845       pwd++;
2846     }				//name and null character
2847 
2848   *ptr = 0;
2849   ptr++;
2850   pwd++;			// skip double null
2851 
2852   if ((flag & 0x0010) == 0)	// normal node: done
2853 
2854     {
2855       *pMenu = pwd;
2856       *psz = ptr;
2857       return (int) flag;
2858     }
2859   //pTemp = ptr;
2860   //ptr += 2;
2861   // popup node: need to go on...
2862   while (1)
2863     {
2864       //num++;
2865       *pMenu = pwd;
2866       *psz = ptr;
2867       flag1 = (WORD) MenuFill (psz, pMenu);
2868       pwd = *pMenu;
2869       ptr = *psz;
2870       if (flag1 & 0x0080)
2871 	break;
2872     }
2873 //  fill # of details to num above
2874   //*(WORD *)pTemp = (WORD)num;
2875   *pMenu = pwd;
2876   *psz = ptr;
2877   return flag;
2878 }
2879 
2880 
2881 //
2882 //==============================================================================
2883 // The following program is based on preorder-tree-traversal.
2884 // once you understand how to traverse.....
2885 // the rest is pretty straight forward.
2886 // still we need to scan it first and fill it next time.
2887 // and finally we can print it.
2888 //
2889 // This function is written by sang cho
2890 //                                                         September 29, 1997
2891 //                                                         revised october 2, 1997
2892 //                             revised october 12, 1997
2893 // ..............................................................................
2894 // ------------------------------------------------------------------------------
2895 // I use same structure - which is used in P.E. programs - for my reporting.
2896 // So, my structure is as follows:
2897 //        # of menu name is stored else where ( in directory I suppose )
2898 //     supermenuname                    null terminated string, only ascii is considered.
2899 //         flag                 tells : node is a leaf or a internal node.
2900 //         popupname                    null terminated string
2901 //
2902 //              flag                normal menu flag (leaf node)
2903 //                      id                                  normal menu id
2904 //              name                    normal menu name
2905 //         or                            or
2906 //              flag                        popup menu flag (internal node)
2907 //              popupname                   popup menu name
2908 //
2909 //                 flag                             it may folows
2910 //                         id                                   normal menu id
2911 //                 name                                 normal menu name
2912 //             or                                 or
2913 //                 flag                                 popup menu
2914 //                 popupname                    popup menu name
2915 //                                 .........
2916 //                                it goes on like this,
2917 //                                 but usually, it only goes a few steps,...
2918 // ------------------------------------------------------------------------------
2919 /* scan menu and copy menu */
2920 int WINAPI
2921 GetContentsOfMenu (
2922 		    LPVOID lpFile,
2923 		    char **pszResTypes)
2924 {
2925   PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage;
2926   PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1;
2927   PIMAGE_RESOURCE_DIR_STRING_U pMenuName;
2928   PIMAGE_RESOURCE_DATA_ENTRY prData;
2929   //PIMAGE_SECTION_HEADER              psh = (PIMAGE_SECTION_HEADER)
2930   //ImageDirectorySection (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE);
2931   PIMAGE_MENU_HEADER pMenuHeader;
2932   //PIMAGE_POPUP_MENU_ITEM pPopup;
2933   WORD* pPopup;
2934   //PIMAGE_NORMAL_MENU_ITEM pNormal;
2935   char buff[32];
2936   int /*nCnt = 0,*/ i, j;
2937   //int num = 0;
2938   int size;
2939   int sLength, nMenus;
2940   WORD flag;
2941   WORD *pwd;
2942   //DWORD prdeName;
2943   //DWORD                   dwBase;    obsolete
2944   char *pMem/*, *pTemp*/;
2945   //BOOL isStrange = FALSE;
2946 
2947 
2948   /* get root directory of resource tree */
2949   if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
2950        (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
2951     return 0;
2952 
2953   /* set pointer to first resource type entry */
2954   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
2955     ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
2956 
2957   for (i = 0; i < prdType->NumberOfIdEntries; i++)
2958     {
2959       if (prde->Name == RT_MENU)
2960 	break;
2961       prde++;
2962     }
2963   if (prde->Name != RT_MENU)
2964     return 0;
2965 
2966   prdName = (PIMAGE_RESOURCE_DIRECTORY)
2967     ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
2968   if (prdName == NULL)
2969     return 0;
2970 
2971   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
2972     ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
2973 
2974   // sometimes previous code tells you lots of things hidden underneath
2975   // I wish I could save all the revisions I made ... but again .... sigh.
2976   //                                  october 12, 1997    sang
2977   //dwBase = (DWORD)((int)lpFile + psh->PointerToRawData - psh->VirtualAddress);
2978 
2979   nMenus = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
2980   sLength = 0;
2981 
2982   for (i = 0; i < prdName->NumberOfNamedEntries; i++)
2983     {
2984       pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U)
2985 	((DWORD) prdType + (prde->Name ^ 0x80000000));
2986       sLength += pMenuName->Length + 1;
2987 
2988       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
2989 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
2990       if (prdLanguage == NULL)
2991 	continue;
2992 
2993       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
2994 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
2995 
2996       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
2997 	((DWORD) prdType + prde1->OffsetToData);
2998       if (prData == NULL)
2999 	continue;
3000 
3001       pMenuHeader = (PIMAGE_MENU_HEADER)
3002 	GetActualAddress (lpFile, prData->OffsetToData);
3003 
3004       //
3005       // normally wVersion and cbHeaderSize should be zero
3006       // but if it is not then nothing is known to us...
3007       // so let's do our best ... namely guessing .... and trying ....
3008       //                      ... and suffering   ...
3009       // it gave me many sleepless (not exactly but I like to say this) nights.
3010       //
3011 
3012       // strange case
3013       if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
3014 	{
3015 	  //isStrange = TRUE;
3016 	  pwd = (WORD *) ((DWORD) pMenuHeader + 16);
3017 	  size = prData->Size;
3018 	  // expect to return the length needed to report.
3019 	  // sixteen more bytes to do something
3020 	  sLength += 16 + size;
3021 	  //StrangeMenuScan (&sLength, &pwd, size);
3022 	}
3023       // normal case
3024       else
3025 	{
3026 	  pPopup = (WORD*)
3027 	    ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
3028 	  while (1)
3029 	    {
3030 	      flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup));
3031 	      if (flag & 0x0080)
3032 		break;
3033 	    }
3034 	}
3035       prde++;
3036     }
3037   for (i = 0; i < prdName->NumberOfIdEntries; i++)
3038     {
3039       sLength += 12;
3040 
3041       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3042 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3043       if (prdLanguage == NULL)
3044 	continue;
3045 
3046       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3047 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3048 
3049       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3050 	((DWORD) prdType + prde1->OffsetToData);
3051       if (prData == NULL)
3052 	continue;
3053 
3054       pMenuHeader = (PIMAGE_MENU_HEADER)
3055 	GetActualAddress (lpFile, prData->OffsetToData);
3056       // strange case
3057       if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
3058 	{
3059 	  pwd = (WORD *) ((DWORD) pMenuHeader + 16);
3060 	  size = prData->Size;
3061 	  // expect to return the length needed to report.
3062 	  // sixteen more bytes to do something
3063 	  sLength += 16 + size;
3064 	  //StrangeMenuScan (&sLength, &pwd, size);
3065 	}
3066       // normal case
3067       else
3068 	{
3069 	  pPopup = (WORD*)
3070 	    ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
3071 	  while (1)
3072 	    {
3073 	      flag = (WORD) MenuScan (&sLength, (WORD **) (&pPopup));
3074 	      if (flag & 0x0080)
3075 		break;
3076 	    }
3077 	}
3078       prde++;
3079     }
3080   //
3081   // allocate memory for menu names
3082   //
3083   *pszResTypes = (char *) calloc (sLength, 1);
3084 
3085   pMem = *pszResTypes;
3086   //
3087   // and start all over again
3088   //
3089   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3090     ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
3091 
3092   for (i = 0; i < prdName->NumberOfNamedEntries; i++)
3093     {
3094       pMenuName = (PIMAGE_RESOURCE_DIR_STRING_U)
3095 	((DWORD) prdType + (prde->Name ^ 0x80000000));
3096 
3097 
3098       for (j = 0; j < pMenuName->Length; j++)
3099 	*pMem++ = (char) (pMenuName->NameString[j]);
3100       *pMem = 0;
3101       pMem++;
3102 
3103 
3104       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3105 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3106       if (prdLanguage == NULL)
3107 	continue;
3108 
3109       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3110 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3111 
3112       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3113 	((DWORD) prdType + prde1->OffsetToData);
3114       if (prData == NULL)
3115 	continue;
3116 
3117       pMenuHeader = (PIMAGE_MENU_HEADER)
3118 	GetActualAddress (lpFile, prData->OffsetToData);
3119       // strange case
3120       if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
3121 	{
3122 	  pwd = (WORD *) ((DWORD) pMenuHeader);
3123 	  size = prData->Size;
3124 	  strcpy (pMem, ":::::::::::");
3125 	  pMem += 12;
3126 	  *(int *) pMem = size;
3127 	  pMem += 4;
3128 	  StrangeMenuFill (&pMem, &pwd, size);
3129 	}
3130       // normal case
3131       else
3132 	{
3133 	  pPopup = (WORD*)
3134 	    ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
3135 	  while (1)
3136 	    {
3137 	      flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup));
3138 	      if (flag & 0x0080)
3139 		break;
3140 	    }
3141 	}
3142       prde++;
3143     }
3144   for (i = 0; i < prdName->NumberOfIdEntries; i++)
3145     {
3146 
3147       sprintf (buff, "MenuId_%04lX", (prde->Name));
3148       strcpy (pMem, buff);
3149       pMem += strlen (buff) + 1;
3150 
3151       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3152 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3153       if (prdLanguage == NULL)
3154 	continue;
3155 
3156       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3157 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3158 
3159       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3160 	((DWORD) prdType + prde1->OffsetToData);
3161       if (prData == NULL)
3162 	continue;
3163 
3164       pMenuHeader = (PIMAGE_MENU_HEADER)
3165 	GetActualAddress (lpFile, prData->OffsetToData);
3166       // strange case
3167       if (pMenuHeader->wVersion | pMenuHeader->cbHeaderSize)
3168 	{
3169 	  pwd = (WORD *) ((DWORD) pMenuHeader);
3170 	  size = prData->Size;
3171 	  strcpy (pMem, ":::::::::::");
3172 	  pMem += 12;
3173 	  *(int *) pMem = size;
3174 	  pMem += 4;
3175 	  StrangeMenuFill (&pMem, &pwd, size);
3176 	}
3177       // normal case
3178       else
3179 	{
3180 	  pPopup = (WORD*)
3181 	    ((DWORD) pMenuHeader + sizeof (IMAGE_MENU_HEADER));
3182 	  while (1)
3183 	    {
3184 	      flag = (WORD) MenuFill (&pMem, (WORD **) (&pPopup));
3185 	      if (flag & 0x0080)
3186 		break;
3187 	    }
3188 	}
3189       prde++;
3190     }
3191 
3192   return nMenus;
3193 }
3194 
3195 
3196 //
3197 // This function is written by sang cho
3198 //                                                         October 12, 1997
3199 //
3200 /* print contents of menu */
3201 int WINAPI
3202 PrintStrangeMenu (
3203 		   char **psz)
3204 {
3205 
3206   //int i, j, k, l;
3207   int num;
3208   //WORD flag1, flag2;
3209   //char buff[128];
3210   char *ptr, *pmax;
3211 
3212   //return dumpMenu (psz, size);
3213 
3214   ptr = *psz;
3215 
3216   if (strncmp (ptr, ":::::::::::", 11) != 0)
3217     {
3218       printf ("\n#### I don't know why!!!");
3219       dumpMenu (psz, 1024);
3220       exit (0);
3221     }
3222 
3223   ptr += 12;
3224   num = *(int *) ptr;
3225   ptr += 4;
3226   pmax = ptr + num;
3227 
3228   *psz = ptr;
3229   return dumpMenu (psz, num);
3230 
3231   // I will write some code later...
3232 
3233 }
3234 
3235 
3236 
3237 
3238 //
3239 // This function is written by sang cho
3240 //                                                         October 2, 1997
3241 //
3242 /* print contents of menu */
3243 int WINAPI
3244 PrintMenu (
3245 	    int indent,
3246 	    char **psz)
3247 {
3248 
3249   int /*i, */ j, k, l;
3250   WORD id /*, num */ ;
3251   WORD flag;
3252   char buff[128];
3253   char *ptr;
3254 
3255 
3256   ptr = *psz;
3257   //num = *(WORD *)ptr;
3258   //ptr += 2;
3259   while (1)
3260     {
3261       flag = *(WORD *) ptr;
3262       if (flag & 0x0010)	// flag == popup
3263 
3264 	{
3265 	  printf ("\n\n");
3266 	  for (j = 0; j < indent; j++)
3267 	    printf (" ");
3268 	  ptr += 2;
3269 	  printf ("%s  {Popup}\n", ptr);
3270 	  ptr += strlen (ptr) + 1;
3271 	  *psz = ptr;
3272 	  PrintMenu (indent + 5, psz);
3273 	  ptr = *psz;
3274 	}
3275       else			// ispopup == 0
3276 
3277 	{
3278 	  printf ("\n");
3279 	  for (j = 0; j < indent; j++)
3280 	    printf (" ");
3281 	  ptr += 2;
3282 	  id = *(WORD *) ptr;
3283 	  ptr += 2;
3284 	  strcpy (buff, ptr);
3285 	  l = strlen (ptr);
3286 	  ptr += l + 1;
3287 	  if (strchr (buff, 0x09) != NULL)
3288 	    {
3289 	      for (k = 0; k < l; k++)
3290 		if (buff[k] == 0x09)
3291 		  break;
3292 	      for (j = 0; j < l - k; j++)
3293 		buff[31 - j] = buff[l - j];
3294 	      for (j = k; j < 32 + k - l; j++)
3295 		buff[j] = 32;
3296 	    }
3297 	  if (strchr (buff, 0x08) != NULL)
3298 	    {
3299 	      for (k = 0; k < l; k++)
3300 		if (buff[k] == 0x08)
3301 		  break;
3302 	      for (j = 0; j < l - k; j++)
3303 		buff[31 - j] = buff[l - j];
3304 	      for (j = k; j < 32 + k - l; j++)
3305 		buff[j] = 32;
3306 	    }
3307 	  printf ("%s", buff);
3308 	  l = strlen (buff);
3309 	  for (j = l; j < 32; j++)
3310 	    printf (" ");
3311 	  printf ("[ID=%04Xh]", id);
3312 	  *psz = ptr;
3313 	}
3314       if (flag & 0x0080)
3315 	break;
3316     }
3317   return 0;
3318 }
3319 
3320 
3321 //
3322 // This function is written by sang cho
3323 //                                                         October 2, 1997
3324 //
3325 /* the format of menu is not known so I'll do my best */
3326 int WINAPI
3327 dumpMenu (
3328 	   char **psz,
3329 	   int size)
3330 {
3331 
3332   int i, j, k, n, l, c;
3333   char buff[32];
3334   char *ptr, *pmax;
3335 
3336   ptr = *psz;
3337   pmax = ptr + size;
3338   for (i = 0; i < (size / 16) + 1; i++)
3339     {
3340       n = 0;
3341       for (j = 0; j < 16; j++)
3342 	{
3343 	  c = (int) (*ptr);
3344 	  if (c < 0)
3345 	    c += 256;
3346 	  buff[j] = c;
3347 	  printf ("%02X", c);
3348 	  ptr++;
3349 	  if (ptr >= pmax)
3350 	    break;
3351 	  n++;
3352 	  if (n % 4 == 0)
3353 	    printf (" ");
3354 	}
3355       n++;
3356       if (n % 4 == 0)
3357 	printf (" ");
3358       l = j;
3359       j++;
3360       for (; j < 16; j++)
3361 	{
3362 	  n++;
3363 	  if (n % 4 == 0)
3364 	    printf ("   ");
3365 	  else
3366 	    printf ("  ");
3367 	}
3368       printf ("   ");
3369       for (k = 0; k < l; k++)
3370 	if (isprint (c = buff[k]))
3371 	  printf ("%c", c);
3372 	else
3373 	  printf (".");
3374       printf ("\n");
3375       if (ptr >= pmax)
3376 	break;
3377     }
3378 
3379   *psz = ptr;
3380   return 0;
3381 }
3382 
3383 
3384 
3385 
3386 //
3387 // This function is written by sang cho
3388 //                                                         October 13, 1997
3389 //
3390 /* scan dialog box and copy dialog box */
3391 int WINAPI
3392 GetContentsOfDialog (
3393 		      LPVOID lpFile,
3394 		      char **pszResTypes)
3395 {
3396   PIMAGE_RESOURCE_DIRECTORY prdType, prdName, prdLanguage;
3397   PIMAGE_RESOURCE_DIRECTORY_ENTRY prde, prde1;
3398   PIMAGE_RESOURCE_DIR_STRING_U pDialogName;
3399   PIMAGE_RESOURCE_DATA_ENTRY prData;
3400   PIMAGE_DIALOG_HEADER pDialogHeader;
3401   //PIMAGE_CONTROL_DATA pControlData;
3402   char buff[32];
3403   int /*nCnt = 0,*/ i, j;
3404   //int num = 0;
3405   int size;
3406   int sLength, nDialogs;
3407   //WORD flag;
3408   WORD *pwd;
3409   //DWORD prdeName;
3410   char *pMem/*, *pTemp*/;
3411   //BOOL isStrange = FALSE;
3412 
3413 
3414   /* get root directory of resource tree */
3415   if ((prdType = (PIMAGE_RESOURCE_DIRECTORY) ImageDirectoryOffset
3416        (lpFile, IMAGE_DIRECTORY_ENTRY_RESOURCE)) == NULL)
3417     return 0;
3418 
3419   /* set pointer to first resource type entry */
3420   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3421     ((DWORD) prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
3422 
3423   for (i = 0; i < prdType->NumberOfIdEntries; i++)
3424     {
3425       if (prde->Name == RT_DIALOG)
3426 	break;
3427       prde++;
3428     }
3429   if (prde->Name != RT_DIALOG)
3430     return 0;
3431 
3432   prdName = (PIMAGE_RESOURCE_DIRECTORY)
3433     ((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3434   if (prdName == NULL)
3435     return 0;
3436 
3437   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3438     ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
3439 
3440 
3441   nDialogs = prdName->NumberOfNamedEntries + prdName->NumberOfIdEntries;
3442   sLength = 0;
3443 
3444   for (i = 0; i < prdName->NumberOfNamedEntries; i++)
3445     {
3446       pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U)
3447 	((DWORD) prdType + (prde->Name ^ 0x80000000));
3448       sLength += pDialogName->Length + 1;
3449 
3450       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3451 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3452       if (prdLanguage == NULL)
3453 	continue;
3454 
3455       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3456 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3457 
3458       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3459 	((DWORD) prdType + prde1->OffsetToData);
3460       if (prData == NULL)
3461 	continue;
3462 
3463       size = prData->Size;
3464       sLength += 4 + size;
3465       prde++;
3466     }
3467   for (i = 0; i < prdName->NumberOfIdEntries; i++)
3468     {
3469       sLength += 14;
3470 
3471       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3472 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3473       if (prdLanguage == NULL)
3474 	continue;
3475 
3476       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3477 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3478 
3479       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3480 	((DWORD) prdType + prde1->OffsetToData);
3481       if (prData == NULL)
3482 	continue;
3483 
3484       size = prData->Size;
3485       sLength += 4 + size;
3486       prde++;
3487     }
3488   //
3489   // allocate memory for menu names
3490   //
3491   *pszResTypes = (char *) calloc (sLength, 1);
3492 
3493   pMem = *pszResTypes;
3494   //
3495   // and start all over again
3496   //
3497   prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3498     ((DWORD) prdName + sizeof (IMAGE_RESOURCE_DIRECTORY));
3499 
3500   for (i = 0; i < prdName->NumberOfNamedEntries; i++)
3501     {
3502       pDialogName = (PIMAGE_RESOURCE_DIR_STRING_U)
3503 	((DWORD) prdType + (prde->Name ^ 0x80000000));
3504 
3505 
3506       for (j = 0; j < pDialogName->Length; j++)
3507 	*pMem++ = (char) (pDialogName->NameString[j]);
3508       *pMem = 0;
3509       pMem++;
3510 
3511 
3512       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3513 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3514       if (prdLanguage == NULL)
3515 	continue;
3516 
3517       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3518 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3519 
3520       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3521 	((DWORD) prdType + prde1->OffsetToData);
3522       if (prData == NULL)
3523 	continue;
3524 
3525       pDialogHeader = (PIMAGE_DIALOG_HEADER)
3526 	GetActualAddress (lpFile, prData->OffsetToData);
3527 
3528 
3529 
3530       pwd = (WORD *) ((DWORD) pDialogHeader);
3531       size = prData->Size;
3532       *(int *) pMem = size;
3533       pMem += 4;
3534       StrangeMenuFill (&pMem, &pwd, size);
3535 
3536       prde++;
3537     }
3538   for (i = 0; i < prdName->NumberOfIdEntries; i++)
3539     {
3540 
3541       sprintf (buff, "DialogId_%04lX", (prde->Name));
3542       strcpy (pMem, buff);
3543       pMem += strlen (buff) + 1;
3544 
3545       prdLanguage = (PIMAGE_RESOURCE_DIRECTORY)
3546 	((DWORD) prdType + (prde->OffsetToData ^ 0x80000000));
3547       if (prdLanguage == NULL)
3548 	{
3549 	  printf ("\nprdLanguage = NULL");
3550 	  exit (0);
3551 	}
3552 
3553       prde1 = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)
3554 	((DWORD) prdLanguage + sizeof (IMAGE_RESOURCE_DIRECTORY));
3555 
3556       prData = (PIMAGE_RESOURCE_DATA_ENTRY)
3557 	((DWORD) prdType + prde1->OffsetToData);
3558       if (prData == NULL)
3559 	{
3560 	  printf ("\nprData = NULL");
3561 	  exit (0);
3562 	}
3563 
3564       pDialogHeader = (PIMAGE_DIALOG_HEADER)
3565 	GetActualAddress (lpFile, prData->OffsetToData);
3566 
3567 
3568       pwd = (WORD *) ((DWORD) pDialogHeader);
3569       size = prData->Size;
3570       *(int *) pMem = size;
3571       pMem += 4;
3572       StrangeMenuFill (&pMem, &pwd, size);
3573 
3574       prde++;
3575     }
3576 
3577   return nDialogs;
3578 }
3579 
3580 
3581 //
3582 // This function is written by sang cho
3583 //                                                         October 14, 1997
3584 //
3585 /* print contents of dialog */
3586 void WINAPI
3587 PrintNameOrOrdinal (
3588 		     char **psz)
3589 {
3590   char *ptr;
3591 
3592   ptr = *psz;
3593   if (*(WORD *) ptr == 0xFFFF)
3594     {
3595       ptr += 2;
3596       printf ("%04X", *(WORD *) ptr);
3597       ptr += 2;
3598     }
3599   else
3600     {
3601       printf ("%c", '"');
3602       while (*(WORD *) ptr)
3603 	{
3604 	  printf ("%c", *ptr);
3605 	  ptr += 2;
3606 	}
3607       ptr += 2;
3608       printf ("%c", '"');
3609     }
3610   *psz = ptr;
3611 }
3612 
3613 
3614 //
3615 // This function is written by sang cho
3616 //                                                         October 14, 1997
3617 //
3618 /* print contents of dialog */
3619 void WINAPI
3620 PrintDialog (
3621 	      char **psz)
3622 {
3623   int i/*, j, k, l, n, c*/;
3624   int num, size;
3625   DWORD flag;
3626   WORD class;
3627   //char buff[32];
3628   char *ptr, *pmax;
3629   BOOL isStrange = FALSE;
3630 
3631   ptr = *psz;
3632   size = *(int *) ptr;
3633   ptr += 4;
3634   pmax = ptr + size;
3635 
3636   // IStype of Dialog Header
3637   flag = *(DWORD *) ptr;
3638   //
3639   // check if flag is right or not
3640   // it has been observed that some dialog information is strange
3641   // and extra work is needed to fix that ... so let's try something
3642   //
3643 
3644   if ((flag & 0xFFFF0000) == 0xFFFF0000)
3645     {
3646       flag = *(DWORD *) (ptr + 12);
3647       num = *(short *) (ptr + 16);
3648       isStrange = TRUE;
3649       ptr += 26;
3650     }
3651   else
3652     {
3653       num = *(short *) (ptr + 8);
3654       ptr += 18;
3655     }
3656   printf (", # of Controls=%03d, Caption:%c", num, '"');
3657 
3658   // Menu name
3659   if (*(WORD *) ptr == 0xFFFF)
3660     ptr += 4;			// ordinal
3661 
3662   else
3663     {
3664       while (*(WORD *) ptr)
3665 	ptr += 2;
3666       ptr += 2;
3667     }				// name
3668 
3669   // Class name
3670   if (*(WORD *) ptr == 0xFFFF)
3671     ptr += 4;			// ordinal
3672 
3673   else
3674     {
3675       while (*(WORD *) ptr)
3676 	ptr += 2;
3677       ptr += 2;
3678     }				// name
3679 
3680   // Caption
3681   while (*(WORD *) ptr)
3682     {
3683       printf ("%c", *ptr);
3684       ptr += 2;
3685     }
3686   ptr += 2;
3687   printf ("%c", '"');
3688 
3689   // FONT present
3690   if (flag & 0x00000040)
3691     {
3692       if (isStrange)
3693 	ptr += 6;
3694       else
3695 	ptr += 2;		// FONT size
3696 
3697       while (*(WORD *) ptr)
3698 	ptr += 2;		// WCHARs
3699 
3700       ptr += 2;			// double null
3701 
3702     }
3703 
3704   // strange case adjust
3705   if (isStrange)
3706     ptr += 8;
3707 
3708   // DWORD padding
3709   if ((ptr - *psz) % 4)
3710     ptr += 4 - ((ptr - *psz) % 4);
3711 
3712   // start reporting .. finally
3713   for (i = 0; i < num; i++)
3714     {
3715       flag = *(DWORD *) ptr;
3716       if (isStrange)
3717 	ptr += 14;
3718       else
3719 	ptr += 16;
3720       printf ("\n     Control::%03d - ID:", i + 1);
3721 
3722       // Control ID
3723       printf ("%04X, Class:", *(WORD *) ptr);
3724       ptr += 2;
3725 
3726       // Control Class
3727       if (*(WORD *) ptr == 0xFFFF)
3728 	{
3729 	  ptr += 2;
3730 	  class = *(WORD *) ptr;
3731 	  ptr += 2;
3732 	  switch (class)
3733 	    {
3734 	    case 0x80:
3735 	      printf ("BUTTON   ");
3736 	      break;
3737 	    case 0x81:
3738 	      printf ("EDIT     ");
3739 	      break;
3740 	    case 0x82:
3741 	      printf ("STATIC   ");
3742 	      break;
3743 	    case 0x83:
3744 	      printf ("LISTBOX  ");
3745 	      break;
3746 	    case 0x84:
3747 	      printf ("SCROLLBAR");
3748 	      break;
3749 	    case 0x85:
3750 	      printf ("COMBOBOX ");
3751 	      break;
3752 	    default:
3753 	      printf ("%04X     ", class);
3754 	      break;
3755 	    }
3756 	}
3757       else
3758 	PrintNameOrOrdinal (&ptr);
3759 
3760       printf (" Text:");
3761 
3762       // Text
3763       PrintNameOrOrdinal (&ptr);
3764 
3765       // nExtraStuff
3766       ptr += 2;
3767 
3768       // strange case adjust
3769       if (isStrange)
3770 	ptr += 8;
3771 
3772       // DWORD padding
3773       if ((ptr - *psz) % 4)
3774 	ptr += 4 - ((ptr - *psz) % 4);
3775     }
3776 
3777   /*
3778      ptr = *psz;
3779      printf("\n");
3780 
3781      for (i=0; i<(size/16)+1; i++)
3782      {
3783      n = 0;
3784      for (j=0; j<16; j++)
3785      {
3786      c = (int)(*ptr);
3787      if (c<0) c+=256;
3788      buff[j] = c;
3789      printf ("%02X",c);
3790      ptr++;
3791      if (ptr >= pmax) break;
3792      n++;
3793      if (n%4 == 0) printf (" ");
3794      }
3795      n++; if (n%4 == 0) printf (" ");
3796      l = j;
3797      j++;
3798      for (; j<16; j++)
3799      { n++; if (n%4 == 0) printf ("   "); else printf ("  "); }
3800      printf ("   ");
3801      for (k=0; k<l; k++)
3802      if (isprint(c=buff[k])) printf("%c", c); else printf(".");
3803      printf ("\n");
3804      if (ptr >= pmax) break;
3805      }
3806    */
3807 
3808   *psz = pmax;
3809 
3810 }
3811 
3812 
3813 
3814 
3815 
3816 
3817 /* function indicates whether debug  info has been stripped from file */
3818 BOOL WINAPI
3819 IsDebugInfoStripped (
3820 		      LPVOID lpFile)
3821 {
3822   PIMAGE_FILE_HEADER pfh;
3823 
3824   pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile);
3825 
3826   return (pfh->Characteristics & IMAGE_FILE_DEBUG_STRIPPED);
3827 }
3828 
3829 
3830 
3831 
3832 /* retrieve the module name from the debug misc. structure */
3833 int WINAPI
3834 RetrieveModuleName (
3835 		     LPVOID lpFile,
3836 		     char **pszModule)
3837 {
3838 
3839   PIMAGE_DEBUG_DIRECTORY pdd;
3840   PIMAGE_DEBUG_MISC pdm = NULL;
3841   int nCnt;
3842 
3843   if (!(pdd = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryOffset (lpFile, IMAGE_DIRECTORY_ENTRY_DEBUG)))
3844     return 0;
3845 
3846   while (pdd->SizeOfData)
3847     {
3848       if (pdd->Type == IMAGE_DEBUG_TYPE_MISC)
3849 	{
3850 	  pdm = (PIMAGE_DEBUG_MISC) ((DWORD) pdd->PointerToRawData + (DWORD) lpFile);
3851 	  *pszModule = (char *) calloc ((nCnt = (strlen ((char *)pdm->Data))) + 1, 1);
3852 	  // may need some unicode business here...above
3853 	  bcopy (pdm->Data, *pszModule, nCnt);
3854 
3855 	  break;
3856 	}
3857 
3858       pdd++;
3859     }
3860 
3861   if (pdm != NULL)
3862     return nCnt;
3863   else
3864     return 0;
3865 }
3866 
3867 
3868 
3869 
3870 
3871 /* determine if this is a valid debug file */
3872 BOOL WINAPI
3873 IsDebugFile (
3874 	      LPVOID lpFile)
3875 {
3876   PIMAGE_SEPARATE_DEBUG_HEADER psdh;
3877 
3878   psdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile;
3879 
3880   return (psdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE);
3881 }
3882 
3883 
3884 
3885 
3886 /* copy separate debug header structure from debug file */
3887 BOOL WINAPI
3888 GetSeparateDebugHeader (
3889 			 LPVOID lpFile,
3890 			 PIMAGE_SEPARATE_DEBUG_HEADER psdh)
3891 {
3892   PIMAGE_SEPARATE_DEBUG_HEADER pdh;
3893 
3894   pdh = (PIMAGE_SEPARATE_DEBUG_HEADER) lpFile;
3895 
3896   if (pdh->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
3897     {
3898       bcopy ((LPVOID) pdh, (LPVOID) psdh, sizeof (IMAGE_SEPARATE_DEBUG_HEADER));
3899       return TRUE;
3900     }
3901 
3902   return FALSE;
3903 }
3904 
3905 //
3906 // I tried to immitate the output of w32dasm disassembler.
3907 // which is a pretty good program.
3908 // but I am disappointed with this program and I myself
3909 // am writting a disassembler.
3910 // This PEdump program is a byproduct of that project.
3911 // so enjoy this program and I hope we will have a little more
3912 // knowledge on windows programming world.
3913 //                                                        .... sang cho
3914 
3915 #define  MAXSECTIONNUMBER 16
3916 #define  MAXNAMESTRNUMBER 40
3917 int
3918 main (
3919        int argc,
3920        char **argv
3921 )
3922 {
3923   DWORD fileType;
3924   LPVOID lpFile;
3925   FILE *my_fp;
3926   IMAGE_DOS_HEADER dosHdr;
3927   PIMAGE_FILE_HEADER pfh;
3928   PIMAGE_OPTIONAL_HEADER poh;
3929   PIMAGE_SECTION_HEADER psh;
3930   //IMAGE_SECTION_HEADER idsh;
3931   IMAGE_SECTION_HEADER shdr[MAXSECTIONNUMBER];
3932   //PIMAGE_IMPORT_MODULE_DIRECTORY pid;
3933 
3934   int nSections;		// number of sections
3935 
3936   int nResources;		// number of resources
3937 
3938   int nMenus;			// number of menus
3939 
3940   int nDialogs;			// number of dialogs
3941 
3942   int nImportedModules;		// number of imported modules
3943 
3944   int nFunctions;		// number of functions in the imported module
3945 
3946   int nExportedFunctions;	// number of exported funcions
3947 
3948   int imageBase;
3949   int entryPoint;
3950 
3951   int i, j, /*k,*/ n;
3952   //int mnsize;
3953   //int nCnt;
3954   //int nSize;
3955   int fsize;
3956   char *pnstr;
3957   char *pst;
3958   char *piNameBuff;		// import module name buffer
3959 
3960   char *pfNameBuff;		// import functions in the module name buffer
3961 
3962   char *peNameBuff;		// export function name buffer
3963 
3964   char *pmNameBuff;		// menu name buffer
3965 
3966   char *pdNameBuff;		// dialog name buffer
3967 
3968   /*
3969    * Check user arguments.
3970    */
3971   if (2 == argc)
3972     {
3973       my_fp = fopen (argv[1], "rb");
3974       if (my_fp == NULL)
3975 	{
3976 	  printf (
3977 		   "%s: can not open input file \"%s\".\n",
3978 		   argv[0],
3979 		   argv[1]
3980 	    );
3981 	  exit (0);
3982 	}
3983     }
3984   else
3985     {
3986       printf (
3987 	       "%s - PE/COFF file dumper\n"
3988 	       "Copyright (c) 1993 Randy Kath (MSDN Technology Group)\n"
3989       "Copyright (c) 1997 Sang Cho (CS & Engineering - Chongju University)\n"
3990       "Copyright (c) 2000 Emanuele Aliberti (ReactOS Development Team)\n\n",
3991 	       argv[0]
3992 	);
3993       printf (
3994 	       "usage: %s input_file_name\n",
3995 	       argv[0]
3996 	);
3997       exit (0);
3998     }
3999   /*
4000    * Get input file's size.
4001    */
4002   /* argv [0], */
4003   fseek (my_fp, 0L, SEEK_END);
4004   fsize = ftell (my_fp);
4005   rewind (my_fp);
4006   /*
4007    * Buffer the file in memory.
4008    */
4009   lpFile = (void *) calloc (fsize, 1);
4010   if (lpFile == NULL)
4011     {
4012       printf (
4013 	       "%s: can not allocate memory.\n",
4014 	       argv[0]
4015 	);
4016       fclose(my_fp);
4017       exit (0);
4018     }
4019   /*
4020    * --- Start of report ---
4021    */
4022   printf ("\n\nDump of file: %s\n\n", argv[1]);
4023 
4024   n = fread (lpFile, fsize, 1, my_fp);
4025   fclose(my_fp);
4026 
4027   if (n == -1)
4028     {
4029       printf (
4030 	       "%s: failed to read the file \"%s\".\n",
4031 	       argv[0],
4032 	       argv[1]
4033 	);
4034       free(lpFile);
4035       exit (0);
4036     }
4037 
4038   GetDosHeader (lpFile, &dosHdr);
4039 
4040   if ((WORD) IMAGE_DOS_SIGNATURE == dosHdr.e_magic)
4041     {
4042       if ((dosHdr.e_lfanew > 4096)
4043 	  || (dosHdr.e_lfanew < 64)
4044 	)
4045 	{
4046 	  printf (
4047 		   "%s: This file is not in PE format; it looks like in DOS format.\n",
4048 		   argv[0]
4049 	    );
4050       free(lpFile);
4051 	  exit (0);
4052 	}
4053     }
4054   else
4055     {
4056       printf (
4057 	"%s: This doesn't look like an executable file (magic = 0x%04x).\n",
4058 	       argv[0],
4059 	       dosHdr.e_magic
4060 	);
4061       free(lpFile);
4062       exit (0);
4063     }
4064 
4065   fileType = ImageFileType (lpFile);
4066 
4067   if (fileType != IMAGE_NT_SIGNATURE)
4068     {
4069       printf (
4070 	       "%s: This file is not in PE format (magic = 0x%08lx).\n",
4071 	       argv[0],
4072 	       fileType
4073 	);
4074       free(lpFile);
4075       exit (0);
4076     }
4077 
4078   //=====================================
4079   // now we can really start processing
4080   //=====================================
4081 
4082   pfh = (PIMAGE_FILE_HEADER) PEFHDROFFSET (lpFile);
4083 
4084   poh = (PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET (lpFile);
4085 
4086   psh = (PIMAGE_SECTION_HEADER) SECHDROFFSET (lpFile);
4087 
4088   nSections = pfh->NumberOfSections;
4089 
4090   imageBase = poh->ImageBase;
4091 
4092   entryPoint = poh->AddressOfEntryPoint;
4093 
4094   if (psh == NULL)
4095   {
4096     free(lpFile);
4097     return 0;
4098   }
4099 
4100   /* store section headers */
4101 
4102   for (i = 0;
4103        i < nSections;
4104        i++
4105     )
4106     {
4107       shdr[i] = *psh++;
4108     }
4109   /*
4110    * Get Code offset and size,
4111    * Data offset and size.
4112    */
4113   for (i = 0;
4114        i < nSections;
4115        i++
4116     )
4117     {
4118       if (poh->BaseOfCode == shdr[i].VirtualAddress)
4119 	{
4120 	  printf (
4121 		   "Code Offset = %08lX, Code Size = %08lX \n",
4122 		   shdr[i].PointerToRawData,
4123 		   shdr[i].SizeOfRawData
4124 	    );
4125 	}
4126       if (((shdr[i].Characteristics) & 0xC0000040) == 0xC0000040)
4127 	{
4128 	  printf (
4129 		   "Data Offset = %08lX, Data Size = %08lX \n",
4130 		   shdr[i].PointerToRawData,
4131 		   shdr[i].SizeOfRawData
4132 	    );
4133 	  break;
4134 	}
4135     }
4136 
4137   printf ("\n");
4138 
4139   printf (
4140 	   "Number of Objects = %04d (dec), Imagebase = %08Xh \n",
4141 	   nSections,
4142 	   imageBase
4143     );
4144   /*
4145    * Object name alignment.
4146    */
4147   for (i = 0;
4148        i < nSections;
4149        i++
4150     )
4151     {
4152       for (j = 0;
4153 	   j < 7;
4154 	   j++
4155 	)
4156 	{
4157 	  if (shdr[i].Name[j] == 0)
4158 	    {
4159 	      shdr[i].Name[j] = 32;
4160 	    }
4161 	}
4162       shdr[i].Name[7] = 0;
4163     }
4164   for (i = 0; i < nSections; i++)
4165     printf ("\n   Object%02d: %8s RVA: %08lX Offset: %08lX Size: %08lX Flags: %08lX ",
4166       i + 1, shdr[i].Name, shdr[i].VirtualAddress, shdr[i].PointerToRawData,
4167 	    shdr[i].SizeOfRawData, shdr[i].Characteristics);
4168   /*
4169    * Get List of Resources.
4170    */
4171   nResources = GetListOfResourceTypes (lpFile, &pnstr);
4172   pst = pnstr;
4173   printf ("\n");
4174   printf ("\n+++++++++++++++++++ RESOURCE INFORMATION +++++++++++++++++++");
4175   printf ("\n");
4176   if (nResources == 0)
4177     printf ("\n        There are no Resources in This Application.\n");
4178   else
4179     {
4180       printf ("\nNumber of Resource Types = %4d (decimal)\n", nResources);
4181       for (i = 0; i < nResources; i++)
4182 	{
4183 	  printf ("\n   Resource Type %03d: %s", i + 1, pst);
4184 	  pst += strlen ((char *) (pst)) + 1;
4185 	}
4186       free ((void *) pnstr);
4187 
4188       printf ("\n");
4189       printf ("\n+++++++++++++++++++ MENU INFORMATION +++++++++++++++++++");
4190       printf ("\n");
4191 
4192       nMenus = GetContentsOfMenu (lpFile, &pmNameBuff);
4193 
4194       if (nMenus == 0)
4195 	{
4196 	  printf ("\n        There are no Menus in This Application.\n");
4197 	}
4198       else
4199 	{
4200 	  pst = pmNameBuff;
4201 	  printf ("\nNumber of Menus = %4d (decimal)", nMenus);
4202 
4203 	  //dumpMenu(&pst, 8096);
4204 	  for (i = 0; i < nMenus; i++)
4205 	    {
4206 	      // menu ID print
4207 	      printf ("\n\n%s", pst);
4208 	      pst += strlen (pst) + 1;
4209 	      printf ("\n-------------");
4210 	      if (strncmp (pst, ":::::::::::", 11) == 0)
4211 		{
4212 		  printf ("\n");
4213 		  PrintStrangeMenu (&pst);
4214 		}
4215 	      else
4216 		{
4217 		  PrintMenu (6, &pst);
4218 		}
4219 	      //else PrintStrangeMenu(&pst);
4220 	    }
4221 	  free ((void *) pmNameBuff);
4222 	  printf ("\n");
4223 	}
4224 
4225       printf ("\n");
4226       printf ("\n+++++++++++++++++ DIALOG INFORMATION +++++++++++++++++++");
4227       printf ("\n");
4228 
4229       nDialogs = GetContentsOfDialog (lpFile, &pdNameBuff);
4230 
4231       if (nDialogs == 0)
4232 	{
4233 	  printf ("\n        There are no Dialogs in This Application.\n");
4234 	}
4235       else
4236 	{
4237 	  pst = pdNameBuff;
4238 	  printf ("\nNumber of Dialogs = %4d (decimal)", nDialogs);
4239 
4240 	  printf ("\n");
4241 
4242 	  for (i = 0; i < nDialogs; i++)
4243 	    {
4244 	      // Dialog ID print
4245 	      printf ("\nName: %s", pst);
4246 	      pst += strlen (pst) + 1;
4247 	      PrintDialog (&pst);
4248 	    }
4249 	  free ((void *) pdNameBuff);
4250 	  printf ("\n");
4251 	}
4252     }
4253 
4254   printf ("\n+++++++++++++++++++ IMPORTED FUNCTIONS +++++++++++++++++++");
4255 
4256   nImportedModules = GetImportModuleNames (lpFile, &piNameBuff);
4257   if (nImportedModules == 0)
4258     {
4259       printf ("\n        There are no imported Functions in This Application.\n");
4260     }
4261   else
4262     {
4263       pnstr = piNameBuff;
4264       printf ("\nNumber of Imported Modules = %4d (decimal)\n", nImportedModules);
4265       for (i = 0; i < nImportedModules; i++)
4266 	{
4267 	  printf ("\n   Import Module %03d: %s", i + 1, pnstr);
4268 	  pnstr += strlen ((char *) (pnstr)) + 1;
4269 	}
4270 
4271       printf ("\n");
4272       printf ("\n+++++++++++++++++++ IMPORT MODULE DETAILS +++++++++++++++++");
4273       pnstr = piNameBuff;
4274       for (i = 0; i < nImportedModules; i++)
4275 	{
4276 	  printf ("\n\n   Import Module %03d: %s \n", i + 1, pnstr);
4277 	  nFunctions = GetImportFunctionNamesByModule (lpFile, pnstr, &pfNameBuff);
4278 	  pnstr += strlen ((char *) (pnstr)) + 1;
4279 	  pst = pfNameBuff;
4280 	  for (j = 0; j < nFunctions; j++)
4281 	    {
4282 	      printf ("\nAddr:%08X hint(%04X) Name: %s",
4283 		      (*(int *) pst), (*(short *) (pst + 4)),
4284 	      //(pst+6));
4285 		      TranslateFunctionName (pst + 6));
4286 	      pst += strlen ((char *) (pst + 6)) + 1 + 6;
4287 	    }
4288 	  free ((void *) pfNameBuff);
4289 	}
4290       free ((void *) piNameBuff);
4291     }
4292 
4293   printf ("\n");
4294   printf ("\n+++++++++++++++++++ EXPORTED FUNCTIONS +++++++++++++++++++");
4295 
4296   nExportedFunctions = GetExportFunctionNames (lpFile, &peNameBuff);
4297   printf ("\nNumber of Exported Functions = %4d (decimal)\n", nExportedFunctions);
4298 
4299   if (nExportedFunctions > 0)
4300     {
4301       pst = peNameBuff;
4302 
4303       for (i = 0; i < nExportedFunctions; i++)
4304 	{
4305 	  printf ("\nAddr:%08X Ord:%4d (%04Xh) Name: %s",
4306 	       (*(int *) pst), (*(WORD *) (pst + 4)), (*(WORD *) (pst + 4)),
4307 	  //(pst+6));
4308 		  TranslateFunctionName (pst + 6));
4309 	  pst += strlen ((char *) (pst + 6)) + 6 + 1;
4310 	}
4311       free ((void *) peNameBuff);
4312     }
4313 
4314   free ((void *) lpFile);
4315 
4316   return 0;
4317 }
4318 
4319 
4320 /* EOF */
4321