home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol12n13.zip / EXELOO.ZIP / EXELOOK.C < prev    next >
Text File  |  1993-06-23  |  62KB  |  1,736 lines

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