home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol12n03.zip / EXELOOK.C < prev    next >
Text File  |  1993-01-12  |  58KB  |  1,621 lines

  1. // ExeLook - Display Information about NT "Portable EXE" (PE) File
  2. // Copyright (C) 1993 Ray Duncan
  3. // PC Magazine * Ziff Davis Publishing
  4. //
  5. // Known limitations:
  6. // Not completely UNICODE-ready yet.
  7. // Not checked out with DLLs which export by ordinal only yet.
  8. // Needs code added to print and to allow viewing of hex contents
  9. // of sections and resources.
  10. //
  11. // Note: 
  12. // Displayed value for "Calculated size of real-mode image" under 
  13. // "MZ Header" is not correct. This is because the NT linker sets 
  14. // the MZ fields incorrectly.
  15. //
  16.  
  17. #define dim(x) (sizeof(x) / sizeof(x[0]))   // returns no. of elements
  18. #define EXENAMESIZE 256                     // max length of path+filename
  19. #define MAXLINES 4096                       // max lines to display
  20.  
  21. // macro to convert mapped memory address to file offset
  22. #define FileOffset(x) ((ULONG) x - (ULONG) pMap)
  23.  
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <windows.h>
  27. #include <commdlg.h>
  28. #include "ExeLook.h"
  29.  
  30. HANDLE hInst;                               // module instance handle
  31. HWND hFrame;                                // handle for frame window
  32. HFONT hFont;                                // handle for nonprop. font
  33.  
  34. INT CharX, CharY;                           // character dimensions
  35. INT LinesPerPage;                           // lines per page
  36. INT CurLine = 0;                            // first line, current page
  37. INT TotLines = 0;                           // total lines to display
  38. INT TopLine = 0;                            // first line of last page
  39. INT DisplayType = IDM_DOSHDR;               // default display type
  40. TCHAR Spaces[256];                          // holds string of blanks
  41. TCHAR *LinePtr[MAXLINES];                   // holds pointers to lines
  42.  
  43. PMZHEADER   pMZHeader;                      // pointers to header 
  44. PPEHEADER   pPEHeader;                      // structures within mapped 
  45. PCOFFHEADER pCoffHeader;                    // executable file
  46. POPTHEADER  pOptHeader;
  47. PSCNHEADER  pFirstScnHeader;            
  48. PSCNHEADER  pIdataHeader;
  49. PMODULEDIR  pIdata;
  50. PSCNHEADER  pRsrcHeader;
  51. PRSRCDIR    pRsrcDirectory;
  52. PDATADIR    pDataDirectory;
  53. PSCNHEADER  pEdataHeader;
  54. PEXPORTDIR  pExportDirectory;
  55.  
  56. INT iTreeLevel = 0;                         // nesting level of tree
  57. TCHAR RsrcName[256];                        // name of current resource
  58. PSTR pRsrcType;                             // name of current type
  59.  
  60. INT hFile = -1;                             // handle for current file
  61. TCHAR szFileName[EXENAMESIZE+1];            // name of current file
  62. LONG FileSize;                              // length of current file
  63. HANDLE hMap = 0;                            // handle, file mapping object
  64. PSTR pMap = NULL;                           // base address, mapping object
  65.  
  66. TCHAR szFrameClass[] = "ExeLook";           // classname for frame window
  67. TCHAR szAppName[] = "EXE Viewer Utility";   // long application name
  68. TCHAR szMenuName[] = "ExeLookMenu";         // name of menu resource
  69. TCHAR szIcon[] = "ExeLookIcon";             // name of icon resource
  70. TCHAR szIni[] = "ExeLook.ini";              // name of private INI file
  71.  
  72. TCHAR szFilter[] = {                        // filters for Open dialog
  73.      "Executable Files\0"        "*.EXE\0"
  74.      "Dynamic Link Libraries\0"  "*.DLL\0"
  75.      "All Files\0"               "*.*\0"
  76.      "\0" } ;
  77.  
  78. TCHAR *DataDirNames[] = {                   // strings for ShowDataDirectory
  79.     "Export Directory",                     // 0
  80.     "Import Directory",                     // 1
  81.     "Resource Directory",                   // 2
  82.     "Exception Directory",                  // 3
  83.     "Security Directory",                   // 4
  84.     "Base Relocation Table",                // 5
  85.     "Debug Directory",                      // 6
  86.     "Description String",                   // 7
  87.     "Machine Value (MIPS GP)",              // 8
  88.     "Thread Local Storage",                 // 9
  89.     "Callback Directory",                   // 10
  90.     "<Unknown>",                            // 11
  91.     "<Unknown>",                            // 12
  92.     "<Unknown>",                            // 13
  93.     "<Unknown>",                            // 14
  94.     "<Unknown>", } ;                        // 15
  95.  
  96. struct decodeUINT SubSystemTable[] = {            
  97.     IMAGE_SUBSYSTEM_UNKNOWN, "Unknown subsystem",
  98.     IMAGE_SUBSYSTEM_NATIVE, "No subsystem required",
  99.     IMAGE_SUBSYSTEM_WINDOWS_GUI, "Windows graphical I/O subsystem",
  100.     IMAGE_SUBSYSTEM_WINDOWS_CUI, "Windows character I/O subsystem",
  101.     IMAGE_SUBSYSTEM_OS2_CUI, "OS/2 character I/O subsystem",
  102.     IMAGE_SUBSYSTEM_POSIX_CUI, "POSIX character I/O subsystem", } ;
  103.  
  104. struct decodeUINT SectionChars[] = {
  105.     IMAGE_SCN_TYPE_REGULAR, "Regular",
  106.     IMAGE_SCN_TYPE_DUMMY, "Dummy",          // reserved 
  107.     IMAGE_SCN_TYPE_NO_LOAD, "Not loaded",
  108.     IMAGE_SCN_TYPE_GROUPED, "16-bit offset code",
  109.     IMAGE_SCN_TYPE_NO_PAD, "Unpadded",
  110.     IMAGE_SCN_TYPE_COPY, "Copy",            // reserved
  111.     IMAGE_SCN_CNT_CODE, "Machine code",
  112.     IMAGE_SCN_CNT_INITIALIZED_DATA, "Initialized data",
  113.     IMAGE_SCN_CNT_UNINITIALIZED_DATA, "Uninitialized data",
  114.     IMAGE_SCN_LNK_OTHER, "Other",           // reserved
  115.     IMAGE_SCN_LNK_INFO, "Information",
  116.     IMAGE_SCN_LNK_OVERLAY, "Overlay",
  117.     IMAGE_SCN_LNK_REMOVE, "Not part of image",
  118.     IMAGE_SCN_LNK_COMDAT, "COMDAT",
  119.     IMAGE_SCN_MEM_DISCARDABLE, "Discardable",
  120.     IMAGE_SCN_MEM_NOT_CACHED, "Not cacheable",
  121.     IMAGE_SCN_MEM_NOT_PAGED, "Not pageable",
  122.     IMAGE_SCN_MEM_SHARED, "Shareable",
  123.     IMAGE_SCN_MEM_EXECUTE, "Executable",
  124.     IMAGE_SCN_MEM_READ, "Readable",
  125.     IMAGE_SCN_MEM_WRITE, "Writeable", } ;
  126.  
  127. struct decodeUINT ImageChars[] = {
  128.     IMAGE_FILE_RELOCS_STRIPPED, "Reloc info stripped",    
  129.     IMAGE_FILE_EXECUTABLE_IMAGE, "Executable",       
  130.     IMAGE_FILE_LINE_NUMS_STRIPPED, "Line numbers stripped",
  131.     IMAGE_FILE_LOCAL_SYMS_STRIPPED, "Local symbols stripped",
  132.     IMAGE_FILE_MINIMAL_OBJECT, "Minimal object",
  133.     IMAGE_FILE_UPDATE_OBJECT, "Update object",
  134.     IMAGE_FILE_16BIT_MACHINE, "16-bit machine",
  135.     IMAGE_FILE_BYTES_REVERSED_LO, "Bytes reversed low",
  136.     IMAGE_FILE_32BIT_MACHINE, "32-bit machine",
  137.     IMAGE_FILE_PATCH, "Patch",
  138.     IMAGE_FILE_SYSTEM, "System file",
  139.     IMAGE_FILE_DLL, "DLL file",
  140.     IMAGE_FILE_BYTES_REVERSED_HI, "Bytes reversed high", } ;
  141.  
  142. struct decodeUINT DllChars[] = {
  143.     IMAGE_LIBRARY_PROCESS_INIT, "Per-process initialization", 
  144.     IMAGE_LIBRARY_PROCESS_TERM, "Per-process termination",
  145.     IMAGE_LIBRARY_THREAD_INIT, "Per-thread initialization",
  146.     IMAGE_LIBRARY_THREAD_TERM, "Per-thread termination", } ;
  147.  
  148. struct decodeUINT MachineType[] = {
  149.     IMAGE_FILE_MACHINE_UNKNOWN, "Unknown machine",
  150.     IMAGE_FILE_MACHINE_I860, "Intel i860",
  151.     IMAGE_FILE_MACHINE_I386, "Intel i386/i486",
  152.     IMAGE_FILE_MACHINE_R3000, "MIPS R3000 little-endian",
  153.     IMAGE_FILE_MACHINE_R4000, "MIPS R4000 little-endian", };
  154.  
  155. struct decodeUINT RsrcType[] = {
  156.     RSRC_CURSOR, "Cursor",
  157.     RSRC_BITMAP, "Bitmap",
  158.     RSRC_ICON, "Icon",          
  159.     RSRC_MENU, "Menu",
  160.     RSRC_DIALOG, "Dialog",
  161.     RSRC_STRING, "String",
  162.     RSRC_FONTDIR, "Font Dir",
  163.     RSRC_FONT, "Font",
  164.     RSRC_ACCELERATOR, "Accelerators", 
  165.     RSRC_RCDATA, "User Defined",
  166.     RSRC_MESSAGETABLE, "Message Table",
  167.     RSRC_GROUP_CURSOR, "Cursor Group",
  168.     RSRC_GROUP_ICON, "Icon Group",
  169.     RSRC_VERSION, "Version",
  170.     RSRC_DLGINCLUDE, "Dlg Include",
  171.     RSRC_NEWBITMAP, "New Bitmap",
  172.     RSRC_NEWMENU, "New Menu",
  173.     RSRC_NEWDIALOG, "New Dialog", } ;
  174.  
  175. //
  176. // Table of window messages supported by FrameWndProc()
  177. // and the functions which correspond to each message.
  178. //
  179. struct decodeMsg frameMsgs[] = {
  180.     WM_PAINT, DoPaint,
  181.     WM_SIZE, DoSize,
  182.     WM_COMMAND, DoCommand,
  183.     WM_CLOSE, DoClose,
  184.     WM_INITMENU, DoInitMenu,
  185.     WM_DESTROY, DoDestroy,
  186.     WM_VSCROLL, DoVScroll, } ;
  187.  
  188. //
  189. // Table of WM_COMMAND menu IDs and their corresponding functions.
  190. //
  191. struct decodeMsg menuMsgs[] = {
  192.     IDM_OPEN, DoMenuOpen,
  193.     IDM_EXIT, DoMenuExit,
  194.     IDM_ABOUT, DoMenuAbout,
  195.     IDM_DOSHDR, DoDisplayType,
  196.     IDM_COFFHDR, DoDisplayType,
  197.     IDM_OPTHDR, DoDisplayType,
  198.     IDM_DATADIR, DoDisplayType,
  199.     IDM_SECT, DoDisplayType, 
  200.     IDM_IMPORT, DoDisplayType, 
  201.     IDM_EXPORT, DoDisplayType,  
  202.     IDM_RESOURCE, DoDisplayType, 
  203.     IDM_RSRCTREE, DoDisplayType, } ;
  204.  
  205. //
  206. // Table of menu IDs for Display popup and their corresponding
  207. // functions and window captions.
  208. //
  209. struct decodeMenuID displayTable[] = {
  210.     IDM_DOSHDR, ShowMZHeader, "DOS (MZ) File Header",
  211.     IDM_COFFHDR, ShowCoffHeader, "COFF File Header", 
  212.     IDM_OPTHDR, ShowOptHeader, "COFF Optional Header", 
  213.     IDM_DATADIR, ShowDataDirectory, "Data Directory", 
  214.     IDM_SECT, ShowSections, "COFF File Sections", 
  215.     IDM_IMPORT, ShowImports, "Module Imports", 
  216.     IDM_EXPORT, ShowExports, "Module Exports", 
  217.     IDM_RESOURCE, ShowResources, "Resources", 
  218.     IDM_RSRCTREE, ShowResourceTree, "Resource Tree", } ;
  219.  
  220. //
  221. // WinMain -- entry point for this application from Windows.
  222. //
  223. INT APIENTRY WinMain(HANDLE hInstance,
  224.     HANDLE hPrevInstance, PSTR pCmdLine, INT nCmdShow)
  225. {
  226.     MSG msg;                                // scratch message storage
  227.     hInst = hInstance;                      // save this instance handle
  228.  
  229.     if(!InitInstance(hInstance, nCmdShow))  // initialize everything
  230.     {
  231.         MessageBox(hFrame, "Initialization failed!", szAppName,
  232.             MB_ICONSTOP | MB_OK);
  233.         return(FALSE);
  234.     }
  235.  
  236.     while(GetMessage(&msg, NULL, 0, 0))     // while message != WM_QUIT
  237.     {
  238.         TranslateMessage(&msg);             // translate virtual key codes
  239.         DispatchMessage(&msg);              // dispatch message to window
  240.     }
  241.  
  242.     TermInstance(hInstance);                // clean up everything
  243.     return(msg.wParam);                     // return code = WM_QUIT value
  244. }
  245.  
  246. //
  247. // InitInstance --- initialization code for this process
  248. //
  249. BOOL InitInstance(HANDLE hInstance, INT nCmdShow)
  250. {
  251.     WNDCLASS  wc;                           // window class info
  252.     HDC hdc;                                // handle for device context
  253.     TEXTMETRIC tm;                          // info about font
  254.     RECT rect;                              // window position & size
  255.     INT i;                                  // scratch variable
  256.  
  257.     // set parameters for frame window class
  258.     wc.style = CS_HREDRAW|CS_VREDRAW;       // class style
  259.     wc.lpfnWndProc = FrameWndProc;          // class callback function
  260.     wc.cbClsExtra = 0;                      // extra per-class data
  261.     wc.cbWndExtra = 0;                      // extra per-window data
  262.     wc.hInstance = hInstance;               // handle of class owner
  263.     wc.hIcon = LoadIcon(hInst, szIcon);     // application icon
  264.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);       // default cursor
  265.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color 
  266.     wc.lpszMenuName =  szMenuName;          // name of menu resource
  267.     wc.lpszClassName = szFrameClass;        // name of window class
  268.  
  269.     if(!RegisterClass(&wc))                 // register window class,       
  270.         return(FALSE);                      // exit if registration fails
  271.     
  272.     for(i = 0; i < MAXLINES; i++)           // initialize all line
  273.         LinePtr[i] = NULL;                  // pointers
  274.  
  275.     hFrame = CreateWindow(                  // create frame window
  276.         szFrameClass,                       // window class name
  277.         szAppName,                          // text for title bar
  278.         WS_OVERLAPPEDWINDOW | WS_VSCROLL,   // window style
  279.         CW_USEDEFAULT, CW_USEDEFAULT,       // default position
  280.         CW_USEDEFAULT, CW_USEDEFAULT,       // default size
  281.         NULL,                               // no parent window
  282.         NULL,                               // use class default menu
  283.         hInstance,                          // window owner
  284.         NULL);                              // unused pointer
  285.  
  286.     if(!hFrame) return(FALSE);              // error, can't create window
  287.  
  288.     hdc = GetDC(hFrame);                    // get device context
  289.     hFont = GetStockObject(SYSTEM_FIXED_FONT);  // handle for nonprop. font
  290.     SelectObject(hdc, hFont);               // realize the font and get
  291.     GetTextMetrics(hdc, &tm);               // the character dimensions
  292.     CharX = tm.tmAveCharWidth;
  293.     CharY = tm.tmHeight + tm.tmExternalLeading;
  294.     ReleaseDC(hFrame, hdc);                 // release device context
  295.  
  296.     GetWindowRect(hFrame, &rect);           // current window pos & size
  297.  
  298.     // read profile for frame window from previous invocation, if any
  299.     rect.left   = GetPrivateProfileInt("Frame", "xul", rect.left, szIni);
  300.     rect.top    = GetPrivateProfileInt("Frame", "yul", rect.top, szIni);
  301.     rect.right  = GetPrivateProfileInt("Frame", "xlr", rect.right, szIni);
  302.     rect.bottom = GetPrivateProfileInt("Frame", "ylr", rect.bottom, szIni);
  303.  
  304.     MoveWindow(hFrame, rect.left, rect.top, // force window size & position
  305.         rect.right-rect.left, rect.bottom-rect.top, TRUE);
  306.  
  307.     // get saved filename from previous invocation and open the file
  308.     GetPrivateProfileString("File", "filename", "", szFileName, 
  309.         EXENAMESIZE, szIni);
  310.     if(szFileName[0])                       
  311.         OpenDataFile();                     
  312.  
  313.     // get display type from previous invocation, default to DOS file header
  314.     DisplayType = GetPrivateProfileInt("Frame", "type", IDM_DOSHDR, szIni);
  315.  
  316.     ShowWindow(hFrame, nCmdShow);           // make frame window visible
  317.  
  318.     // simulate a Display menu command to turn on the menu checkmark
  319.     // for the current display type, and force update of the window
  320.     PostMessage(hFrame, WM_COMMAND, DisplayType, 0);
  321.  
  322.     return(TRUE);                           // return success flag
  323. }
  324.  
  325. //
  326. // TermInstance -- cleanup code for this process
  327. //
  328. BOOL TermInstance(HANDLE hinstance)
  329. {
  330.     return(TRUE);                           // return success flag
  331. }
  332.  
  333. //
  334. // FrameWndProc --- callback function for application frame window.
  335. // Searches frameMsgs[] for message match, runs corresponding function.
  336. //
  337. LONG CALLBACK FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  338. {
  339.     INT i;                                  // scratch variable
  340.  
  341.     for(i = 0; i < dim(frameMsgs); i++)     // decode window message and
  342.     {                                       // run corresponding function
  343.         if(wMsg == frameMsgs[i].Code)
  344.             return((*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  345.     }
  346.  
  347.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  348. }
  349.  
  350. //
  351. // DoCommand -- process WM_COMMAND message for frame window by
  352. // decoding the menubar item with the menuMsgs[] array, then
  353. // running the corresponding function to process the command.
  354. // 
  355. LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  356. {
  357.     INT i;                                  // scratch variable
  358.  
  359.     for(i = 0; i < dim(menuMsgs); i++)      // decode menu command and
  360.     {                                       // run corresponding function
  361.         if(wParam == menuMsgs[i].Code)
  362.             return((*menuMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  363.     }
  364.  
  365.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  366. }
  367.  
  368. //
  369. // DoDestroy -- process WM_DESTROY message for frame window.
  370. // 
  371. LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  372. {
  373.     PostQuitMessage(0);                     // force WM_QUIT message to
  374.     return(0);                              // terminate the event loop
  375. }
  376.  
  377. //
  378. // DoClose -- process WM_CLOSE message for frame window.
  379. // 
  380. LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  381. {
  382.     UpdateProfile();                        // save window size & position
  383.     DestroyWindow(hWnd);                    // then close down app
  384.     return(FALSE);                              
  385. }
  386.  
  387. // 
  388. // DoInitMenu - process WM_INITMENU message, enable/disable menu
  389. // items and set appropriate checkmarks.
  390. //
  391. LONG DoInitMenu(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  392. {
  393.     HMENU hMenu = (HMENU) wParam;
  394.  
  395.     // if imports section was found, enable import menu item
  396.     EnableMenuItem(hMenu, IDM_IMPORT, pIdataHeader ? MF_ENABLED : MF_GRAYED);
  397.  
  398.     // if exports section was found, enable import menu item
  399.     EnableMenuItem(hMenu, IDM_EXPORT, pEdataHeader ? MF_ENABLED : MF_GRAYED);
  400.  
  401.     // if resource section was found, enable resource menu items
  402.     EnableMenuItem(hMenu, IDM_RESOURCE, pRsrcHeader ? MF_ENABLED : MF_GRAYED);
  403.     EnableMenuItem(hMenu, IDM_RSRCTREE, pRsrcHeader ? MF_ENABLED : MF_GRAYED);
  404.  
  405.     return(FALSE);
  406. }
  407.  
  408. //
  409. // DoVScroll -- process WM_VSCROLL message for frame window.
  410. // 
  411. LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  412. {
  413.     RECT rect;
  414.  
  415.     switch(LOWORD(wParam))                  // LOWORD vital for Win32
  416.     {                                   
  417.         case SB_TOP:                        // go to top of output if
  418.             if(CurLine)                     // we aren't there already
  419.             {
  420.                 SetCurLine(0);
  421.                 Repaint();
  422.             }
  423.             break;
  424.  
  425.         case SB_BOTTOM:                     // go to bottom of output if
  426.             if(CurLine < TopLine)           // we aren't there already
  427.             {
  428.                 SetCurLine(TopLine);
  429.                 Repaint();
  430.             }
  431.             break;
  432.  
  433.         case SB_LINEUP:                     // scroll up by one line if
  434.             if(CurLine)                     // we aren't already at top
  435.             {   
  436.                 SetCurLine(CurLine - 1);
  437.                 ScrollWindow(hWnd, 0, CharY, NULL, NULL);
  438.                 UpdateWindow(hWnd);
  439.             }
  440.             break;
  441.  
  442.         case SB_LINEDOWN:                   // scroll down by one line if
  443.             if(CurLine < TopLine)           // we aren't already at bottom
  444.             {
  445.                 SetCurLine(CurLine + 1);
  446.                 ScrollWindow(hWnd, 0, -CharY, NULL, NULL);
  447.                 GetClientRect(hWnd, &rect);
  448.                 rect.top = max(0, (LinesPerPage-1) * CharY);
  449.                 InvalidateRect(hWnd, &rect, TRUE);
  450.                 UpdateWindow(hWnd);
  451.             }
  452.             break;
  453.  
  454.         case SB_PAGEUP:                     // scroll up by one page
  455.             SetCurLine(CurLine - LinesPerPage);
  456.             Repaint();
  457.             break;
  458.  
  459.         case SB_PAGEDOWN:                   // scroll down by one page
  460.             SetCurLine(CurLine + LinesPerPage);
  461.             Repaint();
  462.             break;
  463.  
  464.         case SB_THUMBPOSITION:              // scroll display according
  465.             SetCurLine(THUMBPOS);           // to new thumb position
  466.             Repaint();
  467.             break;
  468.     }
  469.     return(FALSE);                              
  470. }
  471.  
  472. //
  473. // DoPaint -- process WM_PAINT message for frame window.
  474. // 
  475. LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  476. {
  477.     HDC hdc;
  478.     PAINTSTRUCT ps;
  479.     INT i;
  480.  
  481.     hdc = BeginPaint(hWnd, &ps);            // get device context
  482.     SelectObject(hdc, hFont);               // select non-prop. font
  483.  
  484.     for(i = 0; i < LinesPerPage; i++)       // paint lines of text
  485.         PaintLine(hdc, i);                  // in the window
  486.  
  487.     EndPaint(hWnd, &ps);                    // release device context
  488.     return(FALSE);
  489. }
  490.  
  491. //
  492. // DoSize -- process WM_SIZE message for frame window.  Recalculate
  493. // lines per page, if window has grown and at end of file may need to 
  494. // change first line in window and refresh it.
  495. //
  496. LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  497. {
  498.     LinesPerPage = HIWORD(lParam) / CharY;  // window height / char height
  499.     ConfigWindow();                         // calc display parameters
  500.     if(CurLine > TopLine)                   // make sure window refilled
  501.         SetCurLine(TopLine);                // if window got bigger
  502.     return(FALSE);
  503. }
  504.  
  505. //
  506. // DoMenuOpen -- process File-Open command from menu bar. All
  507. // the hard work is done by the OpenFile common dialog.
  508. //
  509. LONG DoMenuOpen(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  510. {
  511.     OPENFILENAME ofn;                       // used by common dialogs
  512.  
  513.     szFileName[0]  = '\0';                  // init filename buffer
  514.  
  515.     ofn.lStructSize = sizeof(OPENFILENAME); // length of structure
  516.     ofn.hwndOwner = hWnd;                   // handle for owner window
  517.     ofn.lpstrFilter = szFilter;             // address of filter list
  518.     ofn.lpstrCustomFilter = NULL;           // custom filter buffer address
  519.     ofn.nFilterIndex = 1;                   // pick default filter
  520.     ofn.lpstrFile = szFileName;             // buffer for path+filename
  521.     ofn.nMaxFile = EXENAMESIZE;             // length of buffer
  522.     ofn.lpstrFileTitle = NULL;              // buffer for filename only
  523.     ofn.lpstrInitialDir = NULL;             // initial directory for dialog
  524.     ofn.lpstrTitle = NULL;                  // title for dialog box
  525.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  526.     ofn.lpstrDefExt = NULL;                 // default extension 
  527.  
  528.     if(GetOpenFileName(&ofn))               // display open dialog
  529.     {
  530.         OpenDataFile();                     // open file for viewing
  531.         PostMessage(hFrame, WM_COMMAND, DisplayType, 0); // update display
  532.     }
  533.  
  534.     return(FALSE);
  535. }
  536.  
  537. //
  538. // DoMenuExit -- process File-Exit command from menu bar.
  539. // 
  540. LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  541. {
  542.     SendMessage (hWnd, WM_CLOSE, 0, 0L);    // send window close message    
  543.     return(FALSE);                          // to shut down the app
  544. }
  545.  
  546. //
  547. // DoDisplayType -- update the display type popup menu, rebuild the 
  548. // formattted information according to the newly selected display 
  549. // type, then refresh the window.
  550. // 
  551. LONG DoDisplayType(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  552. {
  553.     HMENU hMenu;                            // scratch variables
  554.     INT i;
  555.  
  556.     hMenu = GetMenu(hWnd);                  // update popup checkmark
  557.     CheckMenuItem(hMenu, DisplayType, MF_UNCHECKED);
  558.     DisplayType = wParam;                   
  559.     CheckMenuItem(hMenu, DisplayType, MF_CHECKED);
  560.  
  561.     EmptyLines();                           // discard old output
  562.  
  563.     if(hFile != -1)                         // make sure valid file
  564.     {
  565.         // look up the display function and window caption
  566.         // for the currently selected display type
  567.         for(i = 0; i < dim(displayTable); i++)      
  568.         {                                       
  569.             if(wParam == displayTable[i].Code)
  570.             {
  571.                 SetWindowCaption(displayTable[i].Name);
  572.                 (*displayTable[i].Fxn)();
  573.             }
  574.         }
  575.     }
  576.  
  577.     ConfigWindow();                         // configure scroll bar etc.
  578.     Repaint();                              // refresh the window
  579.  
  580.     return(FALSE);
  581. }
  582.  
  583. //
  584. // DoMenuAbout -- process File-About command from menu bar.
  585. // 
  586. LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  587. {
  588.     // allocate a thunk for the dialog callback, then display dialog
  589.     DialogBox(hInst, "AboutBox", hWnd, (WNDPROC) AboutDlgProc);         
  590.     return(FALSE);                              
  591. }
  592.  
  593. //
  594. // AboutDlgProc -- callback routine for About... dialog.  Basically
  595. // ignores all messages except for the OK button, which dismisses dialog.
  596. //
  597. BOOL CALLBACK AboutDlgProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  598. {
  599.     if((msg == WM_COMMAND) && (wParam == IDOK)) 
  600.         EndDialog(hwnd, 0);                 // if OK button, destroy dialog
  601.     else return(FALSE);                     // otherwise ignore message
  602. }
  603.  
  604. //
  605. // ShowMZHeader -- formats contents of Real-mode DOS "Old Exe" (MZ) 
  606. // file header.
  607. //
  608. VOID ShowMZHeader(VOID)
  609. {
  610.     TCHAR temp[256];
  611.     LONG l;
  612.  
  613.     wsprintf(temp, "Header size:\t\t\t%d paragraphs (%d bytes)", 
  614.         pMZHeader->e_cparhdr, pMZHeader->e_cparhdr * 16);
  615.     AddLine(temp);
  616.  
  617.     wsprintf(temp, "Header + program size:\t\t%d (512-byte) pages", 
  618.         pMZHeader->e_cp);
  619.     AddLine(temp);
  620.  
  621.     wsprintf(temp, "Header + program MOD 512:\t%d bytes", 
  622.         pMZHeader->e_cblp);
  623.     AddLine(temp);
  624.  
  625.     l = (pMZHeader->e_cp * 512) - (pMZHeader->e_cparhdr * 16);
  626.     if(pMZHeader->e_cblp) l = l - 512 + pMZHeader->e_cblp;
  627.     wsprintf(temp, "Calculated image size:\t\t%ld bytes", l);
  628.     AddLine(temp);
  629.  
  630.     wsprintf(temp, "Number of relocations:\t\t%d", pMZHeader->e_crlc);
  631.     AddLine(temp);
  632.  
  633.     wsprintf(temp, "Relocation table offset:\t%04Xh bytes", 
  634.         pMZHeader->e_lfarlc);
  635.     AddLine(temp);
  636.  
  637.     wsprintf(temp, "Initial CS:IP:\t\t\t%04X:%04Xh (load address relative)", 
  638.         pMZHeader->e_cs, pMZHeader->e_ip);
  639.     AddLine(temp);
  640.  
  641.     wsprintf(temp, "Initial SS:SP:\t\t\t%04X:%04Xh (load address relative)", 
  642.         pMZHeader->e_ss, pMZHeader->e_sp);
  643.     AddLine(temp);
  644.  
  645.     wsprintf(temp, "Minimum extra allocation:\t%u paragraphs (%d bytes)", 
  646.         pMZHeader->e_minalloc, pMZHeader->e_minalloc * 16);
  647.     AddLine(temp);
  648.  
  649.     wsprintf(temp, "Maximum extra allocation:\t%u paragraphs (%d bytes)", 
  650.         pMZHeader->e_maxalloc, pMZHeader->e_maxalloc * 16);
  651.     AddLine(temp);
  652.  
  653.     wsprintf(temp, "Checksum:\t\t\t%04Xh", pMZHeader->e_csum);
  654.     AddLine(temp);
  655.  
  656.     if(pMZHeader->e_lfarlc >= 0x40)             // check if NE, LE, or PE
  657.     {
  658.         wsprintf(temp, "Protected mode header offset:\t%ld (%08lXh) bytes",
  659.             pMZHeader->e_lfanew, pMZHeader->e_lfanew);
  660.         AddLine(temp);
  661.     }
  662. }
  663.  
  664. //
  665. // ShowCoffHeader -- formats contents of COFF "FileHeader" structure
  666. // embedded within NT "PE" header.
  667. //
  668. VOID ShowCoffHeader(VOID)
  669. {
  670.     TCHAR temp[256];
  671.     TCHAR *p;
  672.     INT i;
  673.  
  674.     p = "Unknown machine type";
  675.  
  676.     for(i = 0; i < dim(MachineType); i++)
  677.     {
  678.         if(MachineType[i].Code == pCoffHeader->Machine)
  679.             p = MachineType[i].Name;
  680.     }
  681.  
  682.     wsprintf(temp, "Machine:\t\t\t%04Xh (%s)", pCoffHeader->Machine, p);
  683.     AddLine(temp);
  684.     
  685.     wsprintf(temp, "Number of sections:\t\t%d", 
  686.         pCoffHeader->NumberOfSections);
  687.     AddLine(temp);
  688.  
  689.     wsprintf(temp, "Time/Date Stamp:\t\t%08Xh", 
  690.         pCoffHeader->TimeDateStamp);
  691.     AddLine(temp);
  692.  
  693.     wsprintf(temp, "Symbol Table Pointer:\t\t%08Xh",
  694.         pCoffHeader->PointerToSymbolTable);
  695.     AddLine(temp);
  696.  
  697.     wsprintf(temp, "Number of Symbols:\t\t%d",
  698.         pCoffHeader->NumberOfSymbols);
  699.     AddLine(temp);
  700.  
  701.     wsprintf(temp, "Optional Header Size:\t\t%d (%0Xh) bytes",
  702.         pCoffHeader->SizeOfOptionalHeader,
  703.         pCoffHeader->SizeOfOptionalHeader);
  704.     AddLine(temp);
  705.  
  706.     wsprintf(temp, "Characteristics:\t\t%04Xh",
  707.         pCoffHeader->Characteristics);
  708.     AddLine(temp);
  709.  
  710.     for(i = 0; i < dim(ImageChars); i++)
  711.     {
  712.         if(ImageChars[i].Code & pCoffHeader->Characteristics)
  713.         {
  714.             wsprintf(temp, "\t\t\t\t%s", ImageChars[i].Name);
  715.             AddLine(temp);
  716.         }
  717.     }
  718. }
  719.  
  720. //
  721. // ShowOptHeader -- formats contents of COFF "OptionalHeader" 
  722. // structure embedded within NT "PE" header.
  723. //
  724. VOID ShowOptHeader(VOID)
  725. {
  726.     TCHAR temp[256];
  727.     TCHAR *p;
  728.     INT i;
  729.  
  730.     wsprintf(temp, "Magic Number:\t\t\t%04Xh",
  731.         pOptHeader->Magic);
  732.     AddLine(temp);
  733.  
  734.     wsprintf(temp, "Linker Major Version Number:\t%d",
  735.         pOptHeader->MajorLinkerVersion);
  736.     AddLine(temp);
  737.  
  738.     wsprintf(temp, "Linker Minor Version Number:\t%d",
  739.         pOptHeader->MinorLinkerVersion);
  740.     AddLine(temp);
  741.  
  742.     wsprintf(temp, "Size of Code:\t\t\t%d (%0Xh) bytes",
  743.         pOptHeader->SizeOfCode,
  744.         pOptHeader->SizeOfCode);
  745.     AddLine(temp);
  746.  
  747.     wsprintf(temp, "Size of Initialized Data:\t%d (%0Xh) bytes",
  748.         pOptHeader->SizeOfInitializedData,
  749.         pOptHeader->SizeOfInitializedData);
  750.     AddLine(temp);
  751.  
  752.     wsprintf(temp, "Size of Uninitialized Data:\t%d (%0Xh) bytes",
  753.         pOptHeader->SizeOfUninitializedData,
  754.         pOptHeader->SizeOfUninitializedData);
  755.     AddLine(temp);
  756.  
  757.     wsprintf(temp, "Address of Entry Point:\t%08Xh",
  758.         pOptHeader->AddressOfEntryPoint);
  759.     AddLine(temp);
  760.  
  761.     wsprintf(temp, "Base of Code:\t\t\t%08Xh",
  762.         pOptHeader->BaseOfCode);
  763.     AddLine(temp);
  764.  
  765.     wsprintf(temp, "Base of Data:\t\t\t%08Xh",
  766.         pOptHeader->BaseOfData);
  767.     AddLine(temp);
  768.  
  769.     wsprintf(temp, "Base of Image:\t\t\t%08Xh",
  770.         pOptHeader->ImageBase);
  771.     AddLine(temp);
  772.  
  773.     wsprintf(temp, "Section Alignment:\t\t%d bytes",
  774.         pOptHeader->SectionAlignment);
  775.     AddLine(temp);
  776.  
  777.     wsprintf(temp, "File Alignment:\t\t%d bytes",
  778.         pOptHeader->FileAlignment);
  779.     AddLine(temp);
  780.  
  781.     wsprintf(temp, "Op Sys Major Version Number:\t%d",
  782.         pOptHeader->MajorOperatingSystemVersion);
  783.     AddLine(temp);
  784.  
  785.     wsprintf(temp, "Op Sys Minor Version Number:\t%d",
  786.         pOptHeader->MinorOperatingSystemVersion);
  787.     AddLine(temp);
  788.  
  789.     wsprintf(temp, "Image Major Version Number:\t%d",
  790.         pOptHeader->MajorImageVersion);
  791.     AddLine(temp);
  792.  
  793.     wsprintf(temp, "Image Minor Version Number:\t%d",
  794.         pOptHeader->MinorImageVersion);
  795.     AddLine(temp);
  796.  
  797.     wsprintf(temp, "Subsyst Major Version Number:\t%d",
  798.         pOptHeader->MajorSubsystemVersion);
  799.     AddLine(temp);
  800.  
  801.     wsprintf(temp, "Subsyst Minor Version Number:\t%d",
  802.         pOptHeader->MinorSubsystemVersion);
  803.     AddLine(temp);
  804.  
  805.     wsprintf(temp, "Size of Image:\t\t\t%d (%0Xh) bytes",
  806.         pOptHeader->SizeOfImage, pOptHeader->SizeOfImage);
  807.     AddLine(temp);
  808.  
  809.     wsprintf(temp, "Size of Headers:\t\t%d (%0Xh) bytes",
  810.         pOptHeader->SizeOfHeaders, pOptHeader->SizeOfHeaders);
  811.     AddLine(temp);
  812.  
  813.     wsprintf(temp, "Checksum:\t\t\t%08Xh",
  814.         pOptHeader->CheckSum);
  815.     AddLine(temp);
  816.  
  817.     p = "Unknown subsystem";
  818.  
  819.     for(i = 0; i < dim(SubSystemTable); i++)
  820.     {
  821.         if(SubSystemTable[i].Code == pOptHeader->Subsystem)
  822.             p = SubSystemTable[i].Name;
  823.     }
  824.  
  825.     wsprintf(temp, "Subsystem:\t\t\t%04Xh (%s)",
  826.         pOptHeader->Subsystem, p);
  827.     AddLine(temp);
  828.  
  829.     wsprintf(temp, "DLL Characteristics:\t\t%04Xh",
  830.         pOptHeader->DllCharacteristics);
  831.     AddLine(temp);
  832.  
  833.     for(i = 0; i < dim(DllChars); i++)
  834.     {
  835.         if(DllChars[i].Code & pOptHeader->DllCharacteristics)
  836.         {
  837.             wsprintf(temp, "\t\t\t\t%s", DllChars[i].Name);
  838.             AddLine(temp);
  839.         }
  840.     }
  841.  
  842.     wsprintf(temp, "Stack Reserve Size:\t\t%d (%0Xh) bytes",
  843.         pOptHeader->SizeOfStackReserve,
  844.         pOptHeader->SizeOfStackReserve);
  845.     AddLine(temp);
  846.  
  847.     wsprintf(temp, "Stack Commit Size:\t\t%d (%0Xh) bytes",
  848.         pOptHeader->SizeOfStackCommit,
  849.         pOptHeader->SizeOfStackCommit);
  850.     AddLine(temp);
  851.  
  852.     wsprintf(temp, "Heap Reserve Size:\t\t%d (%0Xh) bytes",
  853.         pOptHeader->SizeOfHeapReserve,
  854.         pOptHeader->SizeOfHeapReserve);
  855.     AddLine(temp);
  856.  
  857.     wsprintf(temp, "Heap Commit Size:\t\t%d (%0Xh) bytes",
  858.         pOptHeader->SizeOfHeapCommit,
  859.         pOptHeader->SizeOfHeapCommit);
  860.     AddLine(temp);
  861.  
  862.     wsprintf(temp, "Tls Index Address:\t\t%08Xh",
  863.         pOptHeader->AddressOfTlsIndex);
  864.     AddLine(temp);
  865.  
  866.     wsprintf(temp, "Number of Rva And Sizes:\t%d",
  867.         pOptHeader->NumberOfRvaAndSizes);
  868.     AddLine(temp);
  869. }
  870.  
  871. //
  872. // ShowDataDirectory -- formats nonzero slots in the Data Directory
  873. // that is embedded in the COFF "Optional Header."
  874. //
  875. VOID ShowDataDirectory(VOID)
  876. {
  877.     INT i;
  878.     TCHAR temp[256];
  879.  
  880.     AddLine("\t\t\t  Virtual Addr     Size");
  881.  
  882.     for(i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
  883.     {
  884.         if(pDataDirectory[i].VirtualAddress)
  885.         {
  886.             wsprintf(temp, "%-24s  %08Xh    %08XH", 
  887.                      DataDirNames[i],
  888.                      pDataDirectory[i].VirtualAddress,
  889.                      pDataDirectory[i].Size);
  890.             AddLine(temp);
  891.         }   
  892.     }
  893. }
  894.  
  895. //
  896. // ShowSections -- formats information about the COFF sections
  897. // in the executable file.
  898. //
  899. VOID ShowSections(VOID)
  900. {
  901.     TCHAR temp[256], temp2[256];
  902.     UINT i, j;
  903.     PSCNHEADER pCurScnHeader = pFirstScnHeader;
  904.  
  905.     AddLine("\t   Virtual  Raw Data   Relocs   LineNums");
  906.     AddLine("\t  Addr/Size Addr/Size Addr/Cnt  Addr/Cnt  Attributes");
  907.  
  908.     for(i = 0; i < pCoffHeader->NumberOfSections; i++)
  909.     {
  910.         wsprintf(temp, "%-8s %08Xh %08Xh %08Xh %08Xh %08Xh", 
  911.             pCurScnHeader->Name,
  912.             pCurScnHeader->VirtualAddress,
  913.             pCurScnHeader->PointerToRawData,
  914.             pCurScnHeader->PointerToRelocations,
  915.             pCurScnHeader->PointerToLinenumbers,
  916.             pCurScnHeader->Characteristics);
  917.         AddLine(temp);
  918.  
  919.         wsprintf(temp, "         %08Xh %08Xh %08Xh %08Xh ", 
  920.             pCurScnHeader->Misc.VirtualSize,
  921.             pCurScnHeader->SizeOfRawData,
  922.             pCurScnHeader->NumberOfRelocations,
  923.             pCurScnHeader->NumberOfLinenumbers);
  924.         AddLine(temp);
  925.  
  926.         strcpy(temp2, "");
  927.  
  928.         for(j = 0; j < dim(SectionChars); j++)
  929.         {
  930.             if(SectionChars[j].Code & pCurScnHeader->Characteristics)
  931.             {
  932.                 if(strlen(temp2))
  933.                     strcat(temp2, ", ");
  934.                       
  935.                 strcat(temp2, SectionChars[j].Name);
  936.             }
  937.         }
  938.  
  939.         if(strlen(temp2))
  940.         {
  941.             wsprintf(temp, "         %s", temp2);
  942.             AddLine(temp);
  943.         }
  944.  
  945.         pCurScnHeader = (PSCNHEADER) ((PBYTE) pCurScnHeader + 
  946.                         sizeof(IMAGE_SECTION_HEADER));
  947.     }
  948. }
  949.  
  950. //
  951. // ShowImports -- formats names of imported modules and their
  952. // function entry points.
  953. //
  954. VOID ShowImports(VOID)
  955. {
  956.     TCHAR temp[256];                        // formatting buffer
  957.     PMODULEDIR pCurModule = pIdata;         // module directory pointer
  958.     PBYTE pModuleName;                      // module name pointer
  959.     UINT * pImportList;                     // function list pointer
  960.     PIMPORTNAME pImportEntry;               // imported function pointer
  961.  
  962.     if(pIdataHeader == NULL)                // bail if no import section
  963.     {
  964.         PostMessage(hFrame, WM_COMMAND, IDM_SECT, 0);
  965.         return;
  966.     }
  967.  
  968.     // walk through the imported module directory which is found 
  969.     // at the beginning of the file section ".idata"
  970.     while(pCurModule->ModuleName)
  971.     {
  972.         // extract pointer to the imported module's name from
  973.         // the current module directory slot
  974.         pModuleName = (PBYTE) pIdata + pCurModule->ModuleName - 
  975.                       pIdataHeader->VirtualAddress;
  976.  
  977.         // copy the module name to local storage (since ".idata" is
  978.         // in read-only memory), then fold it to upper case for display
  979.         strcpy(temp, pModuleName);
  980.         _strupr(temp);
  981.         AddLine(temp);
  982.  
  983.         // extract a pointer to the list of imported functions for
  984.         // this module from the module directory entry
  985.         pImportList = (UINT *) ((PBYTE) pIdata + pCurModule->ImportList - 
  986.                       pIdataHeader->VirtualAddress);
  987.  
  988.         // walk through the list of pointers to structures for the
  989.         // imported functions until a NULL pointer is encountered
  990.         while(*pImportList)
  991.         {
  992.             // calculate the address of the structure describing this
  993.             // imported function
  994.             pImportEntry = (PIMPORTNAME) ((PBYTE) pIdata + *pImportList - 
  995.                            pIdataHeader->VirtualAddress);
  996.  
  997.             // format the name of the imported function for display
  998.             wsprintf(temp, "\t%s", pImportEntry->Name);
  999.             AddLine(temp);
  1000.  
  1001.             // go to the next imported function for this module
  1002.             pImportList++;
  1003.         }
  1004.  
  1005.         // calculate the address of the next module directory entry
  1006.         pCurModule++;
  1007.     }
  1008. }
  1009.  
  1010. //
  1011. // ShowExports -- formats names, ordinals, hint values, and virtual
  1012. // addresses of exported functions for this module.
  1013. //
  1014. VOID ShowExports(VOID)
  1015. {
  1016.     ULONG i;                                // scratch variable
  1017.     UINT Hint = 0;                          // exported fxn position
  1018.     UINT * pFunctionList;                   // pointer to pointer list
  1019.     PSTR pFunctionName;                     // pointer to name 
  1020.     UINT * pFunctionAddr;                   // pointer to virtual addr
  1021.     USHORT * pFunctionOrdinal;              // pointer to ordinal
  1022.     TCHAR temp[256];                        // formatting buffer 
  1023.  
  1024.     if(pEdataHeader == NULL)                // bail if no export section
  1025.     {
  1026.         PostMessage(hFrame, WM_COMMAND, IDM_SECT, 0);
  1027.         return;
  1028.     }
  1029.  
  1030.     // extract virtual address of list of pointers to exported function
  1031.     // names from export directory, convert virtual to mapped address
  1032.     pFunctionList = (UINT *) ((PBYTE) pExportDirectory + 
  1033.                     (ULONG) pExportDirectory->AddressOfNames - 
  1034.                     pEdataHeader->VirtualAddress);
  1035.  
  1036.     // calculate mapped base address of table of function addresses
  1037.     pFunctionAddr = (UINT *) ((PBYTE) pExportDirectory + 
  1038.                     (ULONG) pExportDirectory->AddressOfFunctions - 
  1039.                     pEdataHeader->VirtualAddress);
  1040.  
  1041.     // calculate mapped base address of table of ordinals which have a
  1042.     // 1:1 correspondence to function names
  1043.     pFunctionOrdinal= (USHORT *) ((PBYTE) pExportDirectory + 
  1044.                       (ULONG) pExportDirectory->AddressOfNameOrdinals - 
  1045.                       pEdataHeader->VirtualAddress);
  1046.  
  1047.     // display title line
  1048.     wsprintf(temp, "%-32s Ordinal  Hint  Virt Addr", "Function Name");
  1049.     AddLine(temp);
  1050.  
  1051.     // now walk through the array of name pointers and display each name
  1052.     // along with function's ordinal, hint number, and virtual address
  1053.     for(i = 0; i < pExportDirectory->NumberOfNames; i++)
  1054.     {
  1055.         // convert virtual address of function name to mapped address
  1056.         pFunctionName = (PSTR) pExportDirectory + (ULONG) *pFunctionList - 
  1057.                         pEdataHeader->VirtualAddress;
  1058.  
  1059.         // format and display information for this function
  1060.         wsprintf(temp, "%-32s  %04Xh  %04Xh  %08Xh", pFunctionName, 
  1061.                  pExportDirectory->Base + *pFunctionOrdinal, Hint,
  1062.                  pFunctionAddr[*pFunctionOrdinal]);
  1063.         AddLine(temp);
  1064.  
  1065.         // advance to next name and corresponding ordinal
  1066.         // count exported functions for "hint" value
  1067.         pFunctionList++;
  1068.         pFunctionOrdinal++;
  1069.         Hint++;
  1070.     }
  1071. }
  1072.  
  1073. //
  1074. // ShowResources -- formats names or IDs, types, addresses, and sizes 
  1075. // of binary resources (icons, dialogs, menus, bitmaps, and so on).
  1076. //
  1077. VOID ShowResources(VOID)
  1078. {
  1079.     TCHAR temp[256];
  1080.  
  1081.     if(pRsrcDirectory == NULL)              // bail if no resource section
  1082.     {
  1083.         PostMessage(hFrame, WM_COMMAND, IDM_SECT, 0);
  1084.         return;
  1085.     }
  1086.  
  1087.     // format title line with spacing to match detail lines
  1088.     wsprintf(temp, "%-24s %-14s %-9s  %-9s  %-9s  %-9s",
  1089.              "Resource Name or ID", "Type", "Virt Addr", 
  1090.              "File Addr", "  Size", "Code Page");
  1091.     AddLine(temp);
  1092.  
  1093.     iTreeLevel = 0;                         // reset nesting level
  1094.     ShowRsrcDir(pRsrcDirectory);            // start with root directory
  1095. }
  1096.  
  1097. //
  1098. // ShowRsrcDir -- traverse directory entries for the specified
  1099. // resource directory. Gets called by its own subroutines to 
  1100. // walk recursively through the entire resource directory tree.
  1101. //
  1102. VOID ShowRsrcDir(PRSRCDIR pCurRsrcDir)
  1103. {
  1104.     PRSRCDIRENTRY  pCurDirEntry;
  1105.     UINT i, j;
  1106.  
  1107.     // calculate address of first entry for this directory
  1108.     pCurDirEntry = (PRSRCDIRENTRY) ((PBYTE) pCurRsrcDir + 
  1109.                    sizeof(IMAGE_RESOURCE_DIRECTORY));
  1110.  
  1111.     // find number of entries (by ID or by name)
  1112.     j = max(pCurRsrcDir->NumberOfNamedEntries, pCurRsrcDir->NumberOfIdEntries);
  1113.  
  1114.     // now go and process each entry 
  1115.     for(i = 0; i < j; i++)
  1116.     {
  1117.         ShowRsrcDirEntry(pCurDirEntry);
  1118.         pCurDirEntry++;
  1119.     }
  1120. }
  1121.  
  1122. //
  1123. // ShowRsrcDirEntry -- process one directory entry.  If at directory
  1124. // level zero, the name field indicates the type of resource.  If at
  1125. // directory level one, the name field indicates the ID or name of
  1126. // a single discrete resource. If at directory level two, the name
  1127. // indicates the language (not handled by this code as we have no 
  1128. // working examples of multilanguage files yet).
  1129. //
  1130. VOID ShowRsrcDirEntry(PRSRCDIRENTRY pCurDirEntry)
  1131. {
  1132.     PRSRCDIRSTR pCurDirString;
  1133.     PRSRCDATAENTRY pCurDataEntry;
  1134.     INT i;
  1135.  
  1136.     // If this is first level of directory, the name field of the
  1137.     // directory entry indicates the resource type.  Find the string 
  1138.     // corresponding to the resource type, save its address for later.
  1139.     if(iTreeLevel == 0)
  1140.     {
  1141.         pRsrcType = "Unknown";
  1142.  
  1143.         for(i = 0; i < dim(RsrcType); i++)
  1144.         {
  1145.             if(RsrcType[i].Code == pCurDirEntry->Name)
  1146.                 pRsrcType = RsrcType[i].Name;
  1147.         }
  1148.     }
  1149.  
  1150.     // Now format the resource name or ID.  If we happen to be at
  1151.     // directory level zero no harm is done, the resulting string will 
  1152.     // just get overwritten during processing of next level.
  1153.     if(pCurDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING)
  1154.     {
  1155.         // calculate file address of UNICODE resource name
  1156.         pCurDirString = (PRSRCDIRSTR) ((PBYTE) pRsrcDirectory + 
  1157.                         (pCurDirEntry->Name &
  1158.                         ~IMAGE_RESOURCE_NAME_IS_STRING));
  1159.  
  1160.         // convert UNICODE resource name to ASCIIZ for later display
  1161.         memset(RsrcName, 0, sizeof(RsrcName));
  1162.         wcstombs(RsrcName, (LPWSTR) pCurDirString->NameString, 
  1163.                  pCurDirString->Length);
  1164.     }
  1165.     else if(pCurDirEntry->Name)             // format ID if nonzero
  1166.     {
  1167.         wsprintf(RsrcName, "%08Xh", pCurDirEntry->Name);
  1168.     }
  1169.  
  1170.     // calculate address of resource data entry for this directory entry
  1171.     pCurDataEntry = (PRSRCDATAENTRY) ((PBYTE) pRsrcDirectory + 
  1172.                     (pCurDirEntry->OffsetToData & 
  1173.                     ~IMAGE_RESOURCE_DATA_IS_DIRECTORY));
  1174.  
  1175.     // if data field of entry points to a resource subdirectory, 
  1176.     // call ShowRsrcDir to process the subdirectory, otherwise, call
  1177.     // ShowRsrcDataEntry to format the resource information.
  1178.     if(pCurDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY)
  1179.     {
  1180.         iTreeLevel++;                           // update nesting level
  1181.         ShowRsrcDir((PRSRCDIR) pCurDataEntry);  // audit subdirectory
  1182.         iTreeLevel--;                           // update nesting level
  1183.     }
  1184.     else ShowRsrcDataEntry(pCurDataEntry);  // audit resource data entry 
  1185. }
  1186.  
  1187. //
  1188. // ShowRsrcDataEntry -- formats and displays the name, type, address,
  1189. // size, and code page of a discrete binary resource, using information
  1190. // in the data entry structure and the resource ID or name and resource 
  1191. // type saved during traversal of the directory tree.
  1192. //
  1193. VOID ShowRsrcDataEntry(PRSRCDATAENTRY pCurDataEntry)
  1194. {
  1195.     TCHAR temp[256];
  1196.  
  1197.     wsprintf(temp, "%-24s %-14s %08Xh  %08Xh  %08Xh  %08Xh",
  1198.              RsrcName,                      // resource name or ID      
  1199.              pRsrcType,                     // resource type
  1200.              pCurDataEntry->OffsetToData,   // virtual address of resource
  1201.              pCurDataEntry->OffsetToData -  // file offset of resource
  1202.                 pRsrcHeader->VirtualAddress + pRsrcHeader->PointerToRawData,
  1203.              pCurDataEntry->Size,           // resource size
  1204.              pCurDataEntry->CodePage);      // resource code page
  1205.     AddLine(temp);
  1206. }
  1207.  
  1208. //
  1209. // ShowResourceTree -- formats and displays a tree-like listing of
  1210. // all resource directories, directory entries, and data entries
  1211. //
  1212. VOID ShowResourceTree(VOID)
  1213. {
  1214.     if(pRsrcDirectory == NULL)              // bail if no resource section
  1215.     {
  1216.         PostMessage(hFrame, WM_COMMAND, IDM_SECT, 0);
  1217.         return;
  1218.     }
  1219.  
  1220.     iTreeLevel = 0;                         // reset tree indent level
  1221.     ShowRsrcTreeDir(pRsrcDirectory);        // start with root directory
  1222. }
  1223.  
  1224. //
  1225. // ShowRsrcTreeDir -- audit a resource directory and all its dependent 
  1226. // data structures. Called recursively to walk through the resource
  1227. // directory tree.
  1228. //
  1229. VOID ShowRsrcTreeDir(PRSRCDIR pCurRsrcDir)
  1230. {
  1231.     PRSRCDIRENTRY  pCurDirEntry;
  1232.     UINT i, j;
  1233.     TCHAR temp[256];
  1234.  
  1235.     // display file offset of this directory
  1236.     wsprintf(temp,"%sDirectory at %08XH", Spaces, FileOffset(pCurRsrcDir));
  1237.     AddLine(temp);
  1238.  
  1239.     // calculate address of first entry for this directory
  1240.     pCurDirEntry = (PRSRCDIRENTRY) ((PBYTE) pCurRsrcDir + 
  1241.                    sizeof(IMAGE_RESOURCE_DIRECTORY));
  1242.  
  1243.     // find number of entries (either by ID or by name)
  1244.     j = max(pCurRsrcDir->NumberOfNamedEntries, pCurRsrcDir->NumberOfIdEntries);
  1245.  
  1246.     for(i = 0; i < j; i++)
  1247.     {
  1248.         // audit each entry for this directory
  1249.         ShowRsrcTreeDirEntry(pCurDirEntry); 
  1250.         pCurDirEntry++;
  1251.     }
  1252. }
  1253.  
  1254. //
  1255. // ShowRsrcTreeDirEntry -- formats and displays the contents of a
  1256. // resource directory entry.  If the directory entry's name
  1257. // field points to a resource directory string record containing 
  1258. // a UNICODE resource name, also displays address of that record.
  1259. //
  1260. VOID ShowRsrcTreeDirEntry(PRSRCDIRENTRY pCurDirEntry)
  1261. {
  1262.     PRSRCDIRSTR pCurDirString;
  1263.     PRSRCDATAENTRY pCurDataEntry;
  1264.     TCHAR temp[256];
  1265.  
  1266.     // format information about current directory entry
  1267.     wsprintf(temp, "%s  Dir Entry at %08XH, Name = %08Xh, Offset = %08Xh", 
  1268.              Spaces, FileOffset(pCurDirEntry), pCurDirEntry->Name, 
  1269.              pCurDirEntry->OffsetToData);
  1270.     AddLine(temp);
  1271.  
  1272.     // format address of directory string structure, if any
  1273.     if(pCurDirEntry->Name & IMAGE_RESOURCE_NAME_IS_STRING)
  1274.     {
  1275.         // calculate file address of UNICODE resource name
  1276.         pCurDirString = (PRSRCDIRSTR) ((PBYTE) pRsrcDirectory + 
  1277.                         (pCurDirEntry->Name &
  1278.                         ~IMAGE_RESOURCE_NAME_IS_STRING));
  1279.  
  1280.         wsprintf(temp, "%s  Dir String at %08Xh", Spaces, 
  1281.                  FileOffset(pCurDirString));
  1282.         AddLine(temp);
  1283.     }
  1284.  
  1285.     // calculate address of resource data entry or subdirectory for 
  1286.     // the current directory entry
  1287.     pCurDataEntry = (PRSRCDATAENTRY) ((PBYTE) pRsrcDirectory + 
  1288.                     (pCurDirEntry->OffsetToData & 
  1289.                     ~IMAGE_RESOURCE_DATA_IS_DIRECTORY));
  1290.  
  1291.     // if data field of entry points to a resource subdirectory, 
  1292.     // call ShowRsrcTreeDir to audit the subdirectory, otherwise, call
  1293.     // ShowRsrcTreeDataEntry to format the resource data entry record.
  1294.     if(pCurDirEntry->OffsetToData & IMAGE_RESOURCE_DATA_IS_DIRECTORY)
  1295.     {
  1296.         SetSpaces(++iTreeLevel);                    // indent tree display
  1297.         ShowRsrcTreeDir((PRSRCDIR) pCurDataEntry);  // audit subdirectory
  1298.         SetSpaces(--iTreeLevel);                    // outdent tree display
  1299.     }
  1300.     else
  1301.         ShowRsrcTreeDataEntry(pCurDataEntry);   // audit resource data entry 
  1302. }
  1303.  
  1304. //
  1305. // ShowRsrcTreeDataEntry -- formats and displays the contents of a 
  1306. // resource data entry record within the resource section header.
  1307. //
  1308. VOID ShowRsrcTreeDataEntry(PRSRCDATAENTRY pCurDataEntry)
  1309. {
  1310.     TCHAR temp[256];
  1311.  
  1312.     wsprintf(temp, "%s  Resource Data Entry at %08Xh", Spaces, 
  1313.              FileOffset(pCurDataEntry));
  1314.     AddLine(temp);
  1315. }
  1316.  
  1317. // 
  1318. // SetSpaces -- creates an ASCIIZ string of spaces whose length
  1319. // depends on the current resource directory tree nesting level.
  1320. //
  1321. VOID SetSpaces(INT iSpaces)
  1322. {
  1323.     memset(Spaces, 0, sizeof(Spaces));
  1324.     memset(Spaces, ' ', iSpaces*4);
  1325. }
  1326.  
  1327. //
  1328. // SetCurLine -- called to set CurLine to valid value, clamped to
  1329. // the range (0...TopLine), and redraw thumb on scroll bar.
  1330. //
  1331. VOID SetCurLine(INT NewLine)
  1332. {
  1333.     CurLine = min(max(NewLine, 0), TopLine);
  1334.     SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
  1335. }
  1336.  
  1337. //
  1338. // ConfigWindow -- Configures various display parameters and scrollbar
  1339. // according to total lines of output, current window size, and the
  1340. // number of lines that will fit into the window.
  1341. //
  1342. VOID ConfigWindow(VOID)
  1343. {
  1344.     // calc line number of first line of last page
  1345.     TopLine = max(TotLines - LinesPerPage,0);
  1346.     
  1347.     // update scroll bar range and thumb position
  1348.     SetScrollRange(hFrame, SB_VERT, 0, TopLine, FALSE);
  1349.     SetScrollPos(hFrame, SB_VERT, CurLine, TRUE);
  1350. }
  1351.  
  1352. //
  1353. // AddLine -- called with a pointer to an ASCIIZ string, allocates
  1354. // memory from the heap to hold the string, puts the pointer
  1355. // to the heap block into the next position in the LinePtr[] array,
  1356. // and updates the total line count.
  1357. //
  1358. VOID AddLine(TCHAR * p)
  1359. {
  1360.     TCHAR * q;                              // scratch pointer
  1361.  
  1362.     if(TotLines == MAXLINES)                // bail out if line pointer
  1363.         return;                             // array is already full
  1364.     q = malloc(strlen(p)+1);                // allocate memory for line
  1365.     if(q == 0)                              // bail out out if no 
  1366.         return;                             // heap space available
  1367.     strcpy(q, p);                           // copy string to heap
  1368.     LinePtr[TotLines] = q;                  // put heap pointer into array
  1369.     TotLines++;                             // count lines of output
  1370. }
  1371.  
  1372. //
  1373. // EmptyLines -- releases all heap blocks in LinePtr[] array,
  1374. // then zeros out the line pointers and the total line count
  1375. //
  1376. VOID EmptyLines(VOID)
  1377. {
  1378.     INT i;                                  // scratch variable
  1379.  
  1380.     for(i = 0; i < MAXLINES; i++)
  1381.     {
  1382.         if(LinePtr[i])                      // if this position in
  1383.         {                                   // the LinePtr array is
  1384.             free(LinePtr[i]);               // nonzero, release the
  1385.             LinePtr[i] = NULL;              // heap block, then zero
  1386.         }                                   // out the LinePtr slot
  1387.     }
  1388.  
  1389.     CurLine = 0;                            // initialize various
  1390.     TotLines = 0;                           // other global variables
  1391.     TopLine = 0;
  1392. }
  1393.  
  1394. //
  1395. // PaintLine -- paint a single line of text in the window.
  1396. // The passed line number is relative to the window, NOT to the
  1397. // total array of formatted output available to be painted.
  1398. //
  1399. VOID PaintLine(HDC hdc, INT RelLine)
  1400. {
  1401.     INT Line = RelLine + CurLine;
  1402.  
  1403.     if(LinePtr[Line])
  1404.         TabbedTextOut(hdc, CharX, RelLine*CharY, LinePtr[Line], 
  1405.             strlen(LinePtr[Line]), 0, NULL, 0);
  1406. }
  1407.  
  1408. //
  1409. // Repaint -- force repaint of all formatted output in main window
  1410. //
  1411. VOID Repaint(VOID)
  1412. {
  1413.     InvalidateRect(hFrame, NULL, TRUE);     // force repaint entire window
  1414. }
  1415.  
  1416. //
  1417. // SetWindowCaption -- concatenate a descriptive string with the 
  1418. // application name, then update the frame window's title bar.
  1419. // If called with NULL pointer, removes any previous description from
  1420. // the title bar, leaving only the application name.
  1421. //
  1422. VOID SetWindowCaption(TCHAR * szDescription)
  1423. {
  1424.     TCHAR szTemp[2*EXENAMESIZE+1];             
  1425.  
  1426.     // if no description string or no file open, display app name only
  1427.     if((szDescription == NULL) || (hFile == -1))
  1428.         SetWindowText(hFrame, szAppName);   
  1429.     else
  1430.     {                                       // otherwise...
  1431.         strcpy(szTemp, szFileName);         // get current filename
  1432.         strcat(szTemp, " - ");              // add separator
  1433.         strcat(szTemp, szDescription);      // add descriptive string
  1434.         SetWindowText(hFrame, szTemp);      // put result into title bar
  1435.     }
  1436. }
  1437.  
  1438. //
  1439. // UpdateProfile() --  saves the current window size and position
  1440. // and display type in the application's private INI file.
  1441. //
  1442. VOID UpdateProfile(VOID)
  1443. {
  1444.     RECT rect;
  1445.     TCHAR temp[20];
  1446.  
  1447.     if(IsIconic(hFrame) || IsZoomed(hFrame)) return;
  1448.  
  1449.     GetWindowRect(hFrame, &rect);           
  1450.  
  1451.     wsprintf(temp,"%d", rect.left);
  1452.     WritePrivateProfileString("Frame", "xul", temp, szIni);
  1453.  
  1454.     wsprintf(temp,"%d", rect.top);
  1455.     WritePrivateProfileString("Frame", "yul", temp, szIni);
  1456.  
  1457.     wsprintf(temp,"%d", rect.right);
  1458.     WritePrivateProfileString("Frame", "xlr", temp, szIni);
  1459.  
  1460.     wsprintf(temp,"%d", rect.bottom);
  1461.     WritePrivateProfileString("Frame", "ylr", temp, szIni);
  1462.  
  1463.     wsprintf(temp,"%d", DisplayType);
  1464.     WritePrivateProfileString("Frame", "type", temp, szIni);
  1465.  
  1466.     if(hFile == -1) return;
  1467.  
  1468.     WritePrivateProfileString("File", "filename", szFileName, szIni);
  1469. }
  1470.  
  1471. //
  1472. // OpenDataFile -- opens the file whose name is found in szFileName[] 
  1473. // and creates memory mapping to the file's contents.  The filename
  1474. // was previously obtained from the INI file or by a call to the
  1475. // OpenFile common dialog.
  1476. //
  1477. VOID OpenDataFile(VOID)
  1478. {
  1479.     TCHAR temp[256];
  1480.  
  1481.     if(hFile != -1)                         // close previous file if any
  1482.         CloseDataFile();                    // and destroy its mappings
  1483.  
  1484.     hFile = _lopen(szFileName, OF_READ);    // try and open the new file
  1485.  
  1486.     if(hFile == -1)                         // bail out if no such file
  1487.     {
  1488.         wsprintf(temp, "Can't open file: %s", szFileName);
  1489.         MessageBox(hFrame, temp, szAppName, MB_ICONSTOP | MB_OK);
  1490.         return;
  1491.     }
  1492.  
  1493.     FileSize = _llseek(hFile, 0, 2);        // get size of file
  1494.     
  1495.     if(FileSize == 0)                       // bail out if file is empty
  1496.     {
  1497.         MessageBox(hFrame, "File is empty!", szAppName, 
  1498.             MB_ICONSTOP | MB_OK);
  1499.         CloseDataFile();
  1500.         return;
  1501.     }
  1502.  
  1503.     // create file mapping object
  1504.     hMap = CreateFileMapping((HANDLE) hFile,
  1505.         (LPSECURITY_ATTRIBUTES) NULL, PAGE_READONLY, 0, 0, (LPSTR) NULL);
  1506.  
  1507.     if(hMap == 0)                           // bail out if no mapping object
  1508.     {
  1509.         MessageBox(hFrame, "Can't create file mapping object!", 
  1510.             szAppName, MB_ICONSTOP | MB_OK);
  1511.         CloseDataFile();
  1512.         return;
  1513.     }
  1514.  
  1515.     pMap = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  1516.  
  1517.     if(pMap == 0)                           // bail out if no mapping object
  1518.     {
  1519.         MessageBox(hFrame, "Can't map view of file!", 
  1520.             szAppName, MB_ICONSTOP | MB_OK);
  1521.         CloseDataFile();
  1522.         return;
  1523.     }
  1524.  
  1525.     ConfigWindow();                         // calc display parameters
  1526.     SetWindowCaption(szFileName);           // put filename in title bar
  1527.     SetHeaderPtrs();                        // set up pointers
  1528. }
  1529.  
  1530. //
  1531. // CloseDataFile -- close any previously opened file, destroy mappings
  1532. // if necessary.
  1533. //
  1534. VOID CloseDataFile(VOID)
  1535. {
  1536.     if(pMap)        UnmapViewOfFile(pMap);  // destroy mapping
  1537.     if(hMap)        CloseHandle(hMap);      // release mapping object
  1538.     if(hFile != -1) _lclose(hFile);         // release file handle
  1539.  
  1540.     hFile = -1;                             // reset everything
  1541.     pMap = NULL;
  1542.     hMap = 0;
  1543.  
  1544.     // remove any previous filename from title bar
  1545.     SetWindowCaption(NULL);
  1546. }
  1547.  
  1548. //
  1549. // SetHeaderPtrs -- validates EXE file or DLL, sets up pointers 
  1550. // to various structures and sections within the NT executable file. 
  1551. // Called after the file has been successfully opened and mapped.
  1552. // 
  1553. VOID SetHeaderPtrs(VOID)
  1554. {
  1555.     UINT i;                                 // scratch variables
  1556.     PSCNHEADER pCurScnHeader;
  1557.  
  1558.     // calculate address of DOS real mode (MZ) file header
  1559.     pMZHeader = (PMZHEADER) pMap;
  1560.  
  1561.     // calculate address of NT protected mode (PE) file header
  1562.     pPEHeader = (PPEHEADER) ((PBYTE) pMZHeader + pMZHeader->e_lfanew);
  1563.  
  1564.     if((pMZHeader->e_magic != IMAGE_DOS_SIGNATURE) ||
  1565.        (pPEHeader->Signature != IMAGE_NT_SIGNATURE))
  1566.     {
  1567.         MessageBox(hFrame, "Not a Windows/NT program or DLL!", szAppName,
  1568.             MB_ICONSTOP | MB_OK);
  1569.         CloseDataFile();
  1570.         return;
  1571.     }
  1572.  
  1573.     // calculate address of COFF File Header and Optional Header
  1574.     pCoffHeader = (PCOFFHEADER) &pPEHeader->FileHeader;
  1575.     pOptHeader = (POPTHEADER) &pPEHeader->OptionalHeader;
  1576.  
  1577.     // calculate address of data directory (embedded in Optional Header)
  1578.     pDataDirectory = (PDATADIR) &pOptHeader->DataDirectory;
  1579.  
  1580.     // calculate address of first section header
  1581.     pFirstScnHeader = (PSCNHEADER) ((PBYTE) pOptHeader + 
  1582.                       pCoffHeader->SizeOfOptionalHeader);
  1583.  
  1584.     // default = no sections found
  1585.     pCurScnHeader = pFirstScnHeader;
  1586.     pIdataHeader = NULL;
  1587.     pIdata = NULL;
  1588.     pEdataHeader = NULL;
  1589.     pExportDirectory = NULL;
  1590.     pRsrcHeader = NULL;
  1591.     pRsrcDirectory = NULL;
  1592.  
  1593.     // look through the section headers to find header for file section
  1594.     // containing import table (.idata), export table (.edata), and
  1595.     // resources (.rsrc).  For each section found, save address of
  1596.     // section header and raw data.
  1597.     for(i = 0; i < pCoffHeader->NumberOfSections; i++)
  1598.     {
  1599.         if(!strcmp(pCurScnHeader->Name, ".idata"))
  1600.         {
  1601.             pIdataHeader = pCurScnHeader;
  1602.             pIdata = (PMODULEDIR) (pMap + pIdataHeader->PointerToRawData);
  1603.         }
  1604.         else if(!strcmp(pCurScnHeader->Name, ".edata"))
  1605.         {
  1606.             pEdataHeader = pCurScnHeader;
  1607.             pExportDirectory = (PEXPORTDIR) (pMap + 
  1608.                                pCurScnHeader->PointerToRawData);
  1609.         }
  1610.         else if(!strcmp(pCurScnHeader->Name, ".rsrc"))
  1611.         {
  1612.             pRsrcHeader = pCurScnHeader;
  1613.             pRsrcDirectory = (PRSRCDIR) (pMap + 
  1614.                              pCurScnHeader->PointerToRawData);
  1615.         }
  1616.  
  1617.         pCurScnHeader++;
  1618.     }
  1619. }
  1620.  
  1621.