home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / spy / symbol.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-10  |  20.0 KB  |  664 lines

  1. /***************************************************************************\
  2.  
  3. Module Name: SYMBOL.C
  4.  
  5. This module contains the code for displaying symbols for a specified address.
  6.  
  7. \***************************************************************************/
  8.  
  9. #define INCL_DOSPROCESS
  10. #define    INCL_GPILCIDS
  11. #define    INCL_WINDIALOGS
  12. #define    INCL_WINFRAMEMGR
  13. #define    INCL_WINHEAP            /* needed for spy.h */
  14. #define    INCL_WININPUT
  15. #define    INCL_WINLISTBOXES
  16. #define    INCL_WINMENUS
  17. #define    INCL_WINMESSAGEMGR
  18. #define    INCL_WINPOINTERS        /* needed for spy.h */
  19. #define    INCL_WINWINDOWMGR
  20. #include <os2.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include "spy.h"
  24. #include "spyhook.h"
  25. #include "symbol.h"
  26.  
  27. WHOISINFO whoIs;
  28. MAPDEF mapdef;
  29. MAPEND mapend;
  30. SEGDEF segdef;
  31. SYMDEF symdef;
  32.  
  33. extern VOID lstrcat(PSZ, PSZ);
  34. extern void OutputString(char [], SHORT);       /* Output string to output devices */
  35. extern  BOOL FValidPointer (CHAR FAR *pVoid, SHORT cbStruct);
  36. extern  BOOL FGuessValidPointer (CHAR FAR *pVoid, SHORT cbStruct);
  37.  
  38.  
  39. extern HWND     hwndSpyFrame;
  40. extern HAB      hab;
  41.  
  42. /* Function prototypes */
  43. HWND HwndFrameFromPID(PID);
  44. VOID GetSymbolInformation(PID, char far *, char *);
  45. VOID NEAR ProcessLNOkButton(HWND);
  46. MRESULT NEAR FormatLNDialog(HWND, PSWP, PRECTL);
  47. VOID NEAR EndLNDialog(HWND);
  48. MRESULT EXPENTRY ListNearDlgProc(HWND, USHORT, MPARAM, MPARAM);
  49.  
  50.  
  51. /***************************************************************************\
  52. * hwnd HwndFrameFromPID(pid)
  53. *
  54. * This function attempts to locate a frame window that was
  55. * created by the specified PID. It returns NULL if none are found.
  56. \***************************************************************************/
  57. HWND HwndFrameFromPID(pid)
  58. PID             pid;
  59. {
  60.     HENUM       henum;
  61.     HWND        hwnd;
  62.     PID         pidWindow;
  63.     TID         tidWindow;
  64.     char        szClassName[50];    /* Class name of window */
  65.     CLASSINFO   classinfo;          /* Information about class */
  66.  
  67.     henum = WinBeginEnumWindows(HWND_DESKTOP);
  68.     if (henum == NULL)
  69.         return (NULL);
  70.  
  71.     while ((hwnd = WinGetNextWindow(henum)) != NULL) {
  72.         WinQueryWindowProcess(hwnd, &pidWindow, &tidWindow);
  73.         WinLockWindow(hwnd, FALSE);
  74.         if (pid == pidWindow) {
  75.             /* See if a frame window */
  76.             WinQueryClassName(hwnd, sizeof(szClassName),
  77.                 (PSZ)szClassName);
  78.             if (WinQueryClassInfo(hab, (PSZ)szClassName, &classinfo) &&
  79.                     (classinfo.flClassStyle & CS_FRAME))
  80.                 break;  /* We have our frame */
  81.         }
  82.     }
  83.  
  84.     WinEndEnumWindows(henum);
  85.     return (hwnd);
  86. }
  87.  
  88.  
  89.  
  90. /***************************************************************************\
  91. * int IdentifyCodeSegment(lpSegInfo, pid, selector)
  92. *
  93. *        Identifies the code selector for the specified process.
  94. *          NOTE: The process is currently ignored, but later will somehow
  95. *          return information in the context of the specified process ID.
  96. \***************************************************************************/
  97. int
  98. pascal near IdentifyCodeSegment( pSegInfo, pid, selector )
  99. PSEGINFO   pSegInfo;
  100. PID         pid;
  101. USHORT      selector;
  102. {
  103.     char far *lp;
  104.     char    *np;
  105.     int     n;
  106.     BYTE    c;
  107.     USHORT  segnum;
  108.     USHORT  seg_ptr;
  109.     USHORT  uTemp;
  110.     int     rc;
  111.     PIDINFO pidinfo;
  112.     HWND    hwndPIDFrame;
  113.  
  114.     /* If new selector matches the current one, then nothing to do */
  115.     if ((pSegInfo->pid == pid) && (pSegInfo->selector == selector))
  116.         return 0;
  117.  
  118.     /*
  119.      * Try to identify the code selector.  We will first try in the context
  120.      * of our process.  If this fails, or if we find that the segment is
  121.      * associated with our program and it is not our PID, we will attempt
  122.      * to get the symbol in the specified PID context, with the help of
  123.      * our hooks.
  124.      */
  125.     DosGetPID(&pidinfo);
  126.     rc = IdentifyCodeSelector( selector, (PWHOISINFO)&whoIs );
  127.     if ((pid != pidinfo.pid) && (rc == 0)) {
  128.         /*
  129.          * User asked for a different context, and symbol was found.
  130.          * If the symbol was in our .exe we will ignore what we found,
  131.          * and try again.
  132.          */
  133.         /* First get past the module name */
  134.         np = whoIs.names;
  135.         while (*np++)
  136.             ;
  137.         /* Now go through the pathname */
  138.         while (*np) {
  139.             if (*np++ == '.') {
  140.                 if (strcmp(np,"EXE") == 0) {
  141.                     rc = 1;     /* It is in our exe, so set errr condition */
  142.                     break;  /* no need to go on */
  143.                 }
  144.             }
  145.         }
  146.     }
  147.  
  148.     if (rc) {
  149.         /*
  150.          * We need to try in other PID context
  151.          */
  152.         if ((pid == pidinfo.pid) ||
  153.                 ((hwndPIDFrame = HwndFrameFromPID(pid)) == NULL))
  154.             return (rc);    /* segment not found or no way to find segment */
  155.  
  156.         /* Lets use the hook */
  157.         SpySetLNSymbolPID(pid, selector);
  158.  
  159.         /* HACK: Send message to frame known to send another message */
  160.         WinSendMsg(hwndPIDFrame, WM_QUERYTASKFOCUS, 0L, 0L);
  161.  
  162.         if (SpyGetLNSymbolSelector(&whoIs) != 0)
  163.             return (1);     /* Still did not find the symbol */
  164.  
  165.     }
  166.  
  167.  
  168.     /* It is a valid code selector, make it the new current selector */
  169.     pSegInfo->selector = selector;
  170.     pSegInfo->pid = pid;
  171.  
  172.     /* Is the new selector in the same module? */
  173.     if (pSegInfo->lpSegName && pSegInfo->whoIs.mte == whoIs.mte)
  174.         pSegInfo->whoIs.segNum = whoIs.segNum;     /* Yes, just copy seg# */
  175.     else {
  176.  
  177.         /* New module, get segment #, mte handle, module name and pathstring */
  178.         pSegInfo->whoIs    = whoIs;
  179.  
  180.         /* Generate separate pointers to module name and pathstring */
  181.         lp = &pSegInfo->whoIs.names[0];
  182.         pSegInfo->lpModName = lp;
  183.         while (*lp++)
  184.             ;
  185.         pSegInfo->lpPathName = lp;
  186.  
  187.         /* Change pathstring extension to be .SYM */
  188.         while (*lp)
  189.             if (*lp++ == '.') {
  190.                 *lp++ = 'S';
  191.                 *lp++ = 'Y';
  192.                 *lp++ = 'M';
  193.                 }
  194.         lp++;
  195.  
  196.         /*
  197.          * No current segment name or symbol name, so make them point to
  198.          * null string
  199.          */
  200.         *lp = 0;
  201.         pSegInfo->lpSegName = lp;
  202.         pSegInfo->lpSymName = 0L;
  203.  
  204.         /* Close any currently open .SYM file and then open the new .SYM file */
  205.         if (pSegInfo->symfh != -1)
  206.             pSegInfo->symfh = DosClose((HFILE)pSegInfo->symfh );
  207.  
  208.         if (DosOpen(pSegInfo->lpPathName, (PHFILE)&pSegInfo->symfh,
  209.                 (PUSHORT)&uTemp,
  210.                 0L, 0, 1, 0x00c0, 0L) == 0) {
  211.  
  212.             /* Read in .SYM file header and save segment count and pointer */
  213.  
  214.             DebugFileRead( pSegInfo->symfh, (PSZ)&mapdef, sizeof( mapdef ) );
  215.             pSegInfo->segcnt = mapdef.seg_cnt;
  216.             pSegInfo->segptr = mapdef.seg_ptr;
  217.  
  218.             /*    Read version of MAPSYM that produced this file.
  219.         If not a version 4 file then ignore the file */
  220.  
  221.             DebugFileSeek( pSegInfo->symfh, (long)-sizeof( mapend ), 2 );
  222.             DebugFileRead( pSegInfo->symfh, (PSZ)&mapend, sizeof( mapend ) );
  223.             if (mapend.ver != 4)
  224.                 pSegInfo->symfh = DosClose( (HFILE)pSegInfo->symfh );
  225.             }
  226.         }
  227.  
  228. /* Point to segment name buffer and make it a null string for now */
  229.  
  230.     lp = pSegInfo->lpSegName;
  231.     *lp = 0;
  232.  
  233. /* If we have an open .SYM file, search for segment definition record */
  234.  
  235.     if (pSegInfo->symfh != -1 && (SHORT) pSegInfo->whoIs.segNum < pSegInfo->segcnt) {
  236.  
  237.     /* Start with first segment definition and read segNum definitions */
  238.  
  239.         seg_ptr = pSegInfo->segptr;
  240.         n = pSegInfo->whoIs.segNum;
  241.         while (n--) {
  242.             DebugFileSeek( pSegInfo->symfh, (long)seg_ptr, 4 );
  243.             DebugFileRead( pSegInfo->symfh, (PSZ)&segdef, sizeof( segdef ) );
  244.             seg_ptr = (USHORT)segdef.nxt_seg;
  245.         }
  246.  
  247.     /* Now read in the segment name string associated with this segment
  248.        and make it a null terminated string */
  249.  
  250.         DebugFileRead( pSegInfo->symfh, (PSZ)(lp),
  251.                        (int)((BYTE)segdef.nam_len) );
  252.         lp += segdef.nam_len;
  253.         *lp++ = 0;
  254.  
  255.     /* Remember the count of symbols for this segment */
  256.  
  257.         pSegInfo->symcnt = segdef.sym_cnt;
  258.  
  259.  
  260.     /* Remember the file offset of the symbols for this segment, which is
  261.        immediately after the segment definition record and name we just read */
  262.  
  263.         pSegInfo->symFPos = DebugFileSeek( pSegInfo->symfh, 0L, 1 );
  264.         }
  265.     else {
  266.     /* If no .SYM file or segment number too big, then make the segnemt name
  267.        be the hex representation of its number */
  268.  
  269.         pSegInfo->symcnt = 0;
  270.  
  271.         segnum = pSegInfo->whoIs.segNum;
  272.         n = 4;
  273.         lp += n;
  274.         while (n--) {
  275.             c = (char)(segnum & (USHORT)0xF);
  276.             segnum >>= 4;
  277.             if (c > 9)
  278.                 c += 'A' - 10;
  279.             else
  280.                 c += '0';
  281.             *--lp = c;
  282.             *lp++ = 0;
  283.         }
  284.  
  285.     /* Null terminate the segment name string */
  286.  
  287.         lp += 4;
  288.         *lp++ = 0;
  289.     }
  290.  
  291. /* Initialize the symbol name pointer to point to a null string, immediately
  292.    after the segment name string just created above. */
  293.  
  294.     pSegInfo->lpSymName = lp;
  295.     *lp = 0;
  296.  
  297.     return 0;
  298. }
  299.  
  300.  
  301. USHORT
  302. pascal near FindSymbol( pSegInfo, offset )
  303. PSEGINFO pSegInfo;
  304. USHORT offset;
  305. {
  306.     USHORT i;
  307.     long symPos;
  308.     char far *lp;
  309.  
  310. /* If no .SYM file then return failure */
  311.  
  312.     if (pSegInfo->symfh == -1)
  313.         return 0xFFFF;
  314.  
  315. /* No symbol found yet, so make it a null string */
  316.  
  317.     lp = pSegInfo->lpSymName;
  318.     *lp = 0;
  319.  
  320. /* Now do a linear search of the symbol definitions for this segment, looking
  321.    for the closest match.  The definitions are stored in sorted order */
  322.  
  323.     symPos = DebugFileSeek( pSegInfo->symfh, (long)pSegInfo->symFPos, 0 );
  324.     i = (USHORT)pSegInfo->symcnt;
  325.     while (i--) {
  326.         DebugFileRead( pSegInfo->symfh, (PSZ)&symdef, sizeof( symdef ) );
  327.  
  328.     /* If this is not our symbol then just remember its offset */
  329.  
  330.         if ((USHORT)symdef.sym_val <= offset) {
  331.             symPos = DebugFileSeek( pSegInfo->symfh, 0L, 1 ) -
  332.                      sizeof( symdef );
  333.  
  334.         /* If exact match, exit this loop */
  335.  
  336.             if ((USHORT)symdef.sym_val == offset)
  337.                 break;
  338.             }
  339.         else
  340.         /* If we went past then exit this loop */
  341.  
  342.             break;
  343.  
  344.     /* Still looking, so seek past this symbols name string to next symbol
  345.        definition */
  346.  
  347.         DebugFileSeek( pSegInfo->symfh, (long)symdef.nam_len, 1 );
  348.         }
  349.  
  350. /* Seek to found symdebol definition and read it in, along with the name */
  351.  
  352.     DebugFileSeek( pSegInfo->symfh, (long)symPos, 0 );
  353.     DebugFileRead( pSegInfo->symfh, (PSZ)&symdef,
  354.                    sizeof( symdef ) );
  355.     DebugFileRead( pSegInfo->symfh, (PSZ)lp,
  356.                    (int)((BYTE)symdef.nam_len) );
  357.  
  358. /* Make the name a null terminated string */
  359.  
  360.     lp += symdef.nam_len;
  361.     *lp++ = 0;
  362.  
  363. /* Return the distance of the passed offset from the value of the symbol */
  364.  
  365.     return offset - symdef.sym_val;
  366. }
  367.  
  368.  
  369.  
  370. /*************************************************************************
  371.  *
  372.  * GetSymbolInformation(pid, pvoidInfo, pszInfo)
  373.  *
  374.  * Purpose: To get information about the supplied address
  375.  */
  376. VOID GetSymbolInformation(pid, pvoidInfo, pszInfo)
  377. PID             pid;
  378. char far        *pvoidInfo;
  379. char            *pszInfo;
  380. {
  381.     SEGINFO     seginfo;
  382.     char        szTemp[256];
  383.     USHORT      uOffsetFromSym;
  384.  
  385.  
  386.     /*
  387.      * First try to find the segment in the segment table.
  388.      */
  389.     if (IdentifyCodeSegment(&seginfo, pid, SELECTOROF(pvoidInfo)) != 0) {
  390.  
  391.         /*
  392.          * It failed to find the segment, ie it was invalid, so
  393.          * Simply return INVALID to caller
  394.          */
  395.         sprintf(pszInfo,"PID:%d %04x:%04x - INVALID", (SHORT)pid,
  396.                 SELECTOROF(pvoidInfo), OFFSETOF(pvoidInfo));
  397.         return;
  398.     }
  399.  
  400.  
  401.     sprintf(pszInfo,"PID:%d %04x:%04x - %Fs ! ", (SHORT)pid,
  402.             SELECTOROF(pvoidInfo), OFFSETOF(pvoidInfo),
  403.             seginfo.lpModName);
  404.  
  405.     if (seginfo.symfh == -1) {
  406.         sprintf(szTemp,"%04x", seginfo.whoIs.segNum);
  407.         strcat(pszInfo, szTemp);
  408.     } else {
  409.         lstrcat((PSZ)pszInfo, seginfo.lpSegName);
  410.     }
  411.  
  412.     uOffsetFromSym = FindSymbol(&seginfo, OFFSETOF(pvoidInfo));
  413.     if (uOffsetFromSym != 0xffff) {
  414.         strcat(pszInfo, ":");
  415.  
  416.         lstrcat((PSZ)pszInfo, seginfo.lpSymName);
  417.         if (uOffsetFromSym != 0) {
  418.             sprintf(szTemp, "+%x", uOffsetFromSym);
  419.             strcat(pszInfo, szTemp);
  420.         }
  421.     }
  422. }
  423.  
  424.  
  425. /***************************************************************************\
  426. * VOID NEAR ProcessLNOkButton(hwndDlg)
  427. *
  428. * Process the Ok Button for the List Near Dlg proc
  429. \***************************************************************************/
  430. VOID NEAR ProcessLNOkButton(hwndDlg)
  431. HWND hwndDlg;
  432. {
  433.     char        szTemp[100];
  434.     char far    *pVoid;
  435.     PID         pid;
  436.     SHORT       item;
  437.  
  438.     /*
  439.      * For now try using sscanf to convert the string into a
  440.      * pointer.
  441.      */
  442.     WinQueryDlgItemShort(hwndDlg, DID_PID, &pid, FALSE);
  443.     WinQueryDlgItemText(hwndDlg, DID_ADDR, sizeof(szTemp), szTemp);
  444.     if ((strchr(szTemp,':') != NULL) && (sscanf(szTemp,"%p", &pVoid)) > 0) {
  445.         /* It translated, so try to get info about pointer */
  446.         GetSymbolInformation(pid, pVoid, szTemp);
  447.  
  448.         /* For now simply output to output areas */
  449.         item = SHORT1FROMMR(WinSendDlgItemMsg(hwndDlg, DID_SYMLIST,
  450.                 LM_INSERTITEM, (MPARAM)LIT_END, (MPARAM)(PSZ)szTemp));
  451.  
  452.         WinSendDlgItemMsg(hwndDlg, DID_SYMLIST, LM_SETTOPINDEX,
  453.                 (MPARAM)item, 0L);
  454.     }
  455.  
  456.     /*
  457.      * Now clear the text out of the ADDR field, and set the focus
  458.      * back to the window
  459.      */
  460.     WinSetDlgItemText(hwndDlg, DID_ADDR, "");
  461.     WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwndDlg, DID_ADDR));
  462. }
  463.  
  464. /***************************************************************************\
  465. * MRESULT NEAR FormatLNDialog(hwndDlg, paswp, prectl)
  466. *
  467. * Process the WM_SIZE message in the List Near Dialog
  468. \***************************************************************************/
  469. MRESULT NEAR FormatLNDialog(hwndDlg, paswp, prclClientX)
  470. HWND                hwndDlg;
  471. PSWP                paswp;
  472. PRECTL              prclClientX;
  473. {
  474.     USHORT          cy;
  475.     USHORT          cswp;
  476.     HPS             hps;
  477.     SHORT           dy;
  478.     register HWND   hwndT;
  479.     FONTMETRICS     fm;
  480.     PSWP            pswpT;
  481.     RECTL           rclClient;
  482.     SWP             swpOk;
  483.     SHORT           y;
  484.  
  485.     /*
  486.      * First let the default frame processing set up the position of
  487.      * all of the standard controls.  Then we will position the list box
  488.      * and the two entry fields to fill in the remainder of the space.
  489.      */
  490.  
  491. #define PSWPLN(x) (paswp + cswp + x - DID_SYMLIST)
  492.  
  493.  
  494.     cswp = SHORT1FROMMR(WinDefDlgProc(hwndDlg, WM_FORMATFRAME, (MPARAM)paswp,
  495.             (MPARAM)(PRECTL)&rclClient));
  496.     if (prclClientX != NULL)
  497.         *prclClientX = rclClient;   /* Give caller info */
  498.  
  499.  
  500.     /*
  501.      * Now Add our controls to the SWP list - Verify that the first one
  502.      * exists. If not, we probably are initializing the dialog, so
  503.      * Simply return what the default Dlg Proc returned.
  504.      */
  505.     hwndT = WinWindowFromID(hwndDlg, DID_OK);
  506.     if (hwndT == NULL)
  507.         return ((MRESULT) cswp);
  508.  
  509.     /*
  510.      * We need to get a PS, such that we can find out the size of the
  511.      * font, to adjust our edit fields such that they wont keep moving
  512.      * in.
  513.      */
  514.     hps = WinGetPS(hwndDlg);
  515.     GpiQueryFontMetrics(hps, (LONG)sizeof(fm), &fm);
  516.     WinReleasePS(hps);
  517.  
  518.     WinQueryWindowPos(hwndT, &swpOk);
  519.  
  520.     pswpT=PSWPLN(DID_SYMLIST);
  521.     WinQueryWindowPos(hwndT = WinWindowFromID(hwndDlg, DID_SYMLIST), pswpT);
  522.     dy = pswpT->y - (swpOk.y + swpOk.cy);
  523.     pswpT->fs = SWP_SIZE;
  524.     pswpT->cx = (SHORT)rclClient.xRight - (SHORT)rclClient.xLeft - pswpT->x;
  525.  
  526.     /* First position the top line, just below titlebar */
  527.     pswpT=PSWPLN(DID_PIDLABEL);
  528.     WinQueryWindowPos(hwndT = WinWindowFromID(hwndDlg, DID_PIDLABEL), pswpT);
  529.     pswpT->fs = SWP_MOVE;
  530.     cy = pswpT->cy;
  531.     y = pswpT->y = (SHORT)rclClient.yTop - (SHORT)rclClient.yBottom -
  532.             cy - dy;
  533.  
  534.     pswpT=PSWPLN(DID_PID);
  535.     WinQueryWindowPos(hwndT = WinWindowFromID(hwndDlg, DID_PID), pswpT);
  536.     pswpT->fs = SWP_MOVE;
  537.     pswpT->x += (SHORT)fm.lAveCharWidth / 2; /* Take care of margin */
  538.     pswpT->y = y;
  539.  
  540.     /* Since Edit control is bigger Setup Start Y for the next row */
  541.     y += (cy - pswpT->cy);
  542.  
  543.  
  544.     /* Now position Addr line below PID line */
  545.     pswpT=PSWPLN(DID_ADDRLABEL);
  546.     WinQueryWindowPos(hwndT = WinWindowFromID(hwndDlg, DID_ADDRLABEL), pswpT);
  547.     pswpT->fs = SWP_MOVE;
  548.     y = (pswpT->y = y - pswpT->cy - dy);
  549.  
  550.     pswpT=PSWPLN(DID_ADDR);
  551.     WinQueryWindowPos(hwndT = WinWindowFromID(hwndDlg, DID_ADDR), pswpT);
  552.     pswpT->fs = SWP_MOVE;
  553.     pswpT->x += (SHORT)fm.lAveCharWidth / 2; /* Take care of margin */
  554.     pswpT->y = y;
  555.  
  556.     /* Now set size of listbox */
  557.     y += (cy - pswpT->cy);
  558.  
  559.     pswpT=PSWPLN(DID_SYMLIST);
  560.     pswpT->cy = y - dy - pswpT->y;
  561.  
  562.  
  563.     /*
  564.      * Return the count of swps
  565.      */
  566.     return ((MRESULT)(cswp + (DID_PID-DID_SYMLIST+1)));
  567. }
  568.  
  569.  
  570.  
  571.  
  572. /***************************************************************************\
  573. * VOID NEAR EndLNDialog(hwndDlg)
  574. *
  575. * End processing for the List Near Dialog
  576. \***************************************************************************/
  577. VOID NEAR EndLNDialog(hwndDlg)
  578. HWND hwndDlg;
  579. {
  580.     /* First Dismiss the dialog and destroy the windows */
  581.     WinDismissDlg(hwndDlg, 0);
  582.     WinDestroyWindow(hwndDlg);
  583.  
  584.     /* And re-enable the menu item */
  585.     WinSendMsg(WinWindowFromID(hwndSpyFrame, FID_MENU),
  586.         MM_SETITEMATTR, MPFROM2SHORT(CMD_LISTNEAR, TRUE),
  587.         MPFROM2SHORT(MIA_DISABLED, 0));
  588.  
  589. }
  590.  
  591.  
  592.  
  593. /***************************************************************************\
  594. * MRESULT EXPENTRY ListNearDlgProc(hwnd, msg, mp1, mp2)
  595. *
  596. * Will locate the symbol near the specified address.
  597. \***************************************************************************/
  598. MRESULT EXPENTRY ListNearDlgProc(hwnd, msg, mp1, mp2)
  599. HWND            hwnd;
  600. USHORT          msg;
  601. MPARAM          mp1;
  602. MPARAM          mp2;
  603. {
  604.     PIDINFO     pidinfo;
  605.  
  606.     switch (msg) {
  607.  
  608.     case WM_INITDLG:
  609.         /* Initialize the dialog items */
  610.         WinSetDlgItemText(hwnd, DID_ADDR, "");
  611.         DosGetPID(&pidinfo);
  612.         WinSetDlgItemShort(hwnd, DID_PID, (USHORT)pidinfo.pid, FALSE);
  613.         break;
  614.  
  615.     case WM_SYSCOMMAND:
  616.         if (SHORT1FROMMP(mp1) == SC_CLOSE) {
  617.             /* End processing the dialog */
  618.             EndLNDialog(hwnd);
  619.             break;
  620.         } else
  621.             return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  622.  
  623.  
  624.     case WM_COMMAND:
  625.         switch (SHORT1FROMMP(mp1)) {
  626.         case DID_OK:
  627.  
  628.             /*
  629.              * Process The Ok Button, by caling ProcessLNOkButton, which
  630.              * will add the information to the listbox in our dialog.
  631.              */
  632.             ProcessLNOkButton(hwnd);
  633.             break;
  634.  
  635.         case DID_CANCEL:
  636.             /* End processing the dialog */
  637.             EndLNDialog(hwnd);
  638.             break;
  639.         }
  640.  
  641.         break;
  642.  
  643.     /*
  644.      * We want to add our controls into the formating of the frame, so
  645.      * we need to add some room onto the SWP list
  646.      */
  647.     case WM_QUERYFRAMECTLCOUNT:
  648.         return((MRESULT)(SHORT1FROMMR(WinDefDlgProc(hwnd, msg, mp1, mp2)) +
  649.                 (SHORT)(DID_PID-DID_SYMLIST+1)));
  650.         break;
  651.  
  652.     /*
  653.      * Call FormatLNDialog, to format the dialog
  654.      */
  655.     case WM_FORMATFRAME:
  656.         return (FormatLNDialog(hwnd, (PSWP)mp1, (PRECTL)mp2));
  657.  
  658.     default:
  659.         return(WinDefDlgProc(hwnd, msg, mp1, mp2));
  660.     }
  661.  
  662.     return (0L);
  663. }
  664.