home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / MSJV3-3.ZIP / WINDEBUG.ALL < prev   
Text File  |  1988-04-28  |  26KB  |  1,032 lines

  1. Microsoft Systems Journal
  2. Volume 3; Issue 3; May, 1988
  3.  
  4. Code Listings For:
  5.  
  6.     DEBUG & BUGTEST
  7.     pp. 64-72
  8.  
  9.  
  10. Author(s): Kevin P. Welch
  11. Title:     Debug Microsoft Windows Programs More Effectively with a 
  12.            Simple Utility
  13.  
  14.  
  15.  
  16. Code Listings NOT INCLUDED in Article (referred to on page 66, middle column)
  17. =============================================================================
  18.  
  19.  
  20. Debug MAKE File
  21. ===============
  22.  
  23.  
  24. CFLAGS=-c -u -Asnw -FPa -Gsw -Os -Zep 
  25.  
  26. debug.obj: debug.h debug.c
  27.    cl $(CFLAGS) debug.c
  28.  
  29.  
  30.  
  31. ==============================================================================
  32.  
  33.  
  34. /*
  35.  * WINDOWS 2.00 DEBUG UTILITY - HEADER FILE (DEBUG.H)
  36.  *
  37.  * LANGUAGE : Microsoft C 5.0
  38.  * MODEL    : small or medium
  39.  * STATUS   : operational
  40.  *
  41.  * 12/11/87 1.00 - Kevin P. Welch - initial creation.
  42.  *
  43.  */
  44.  
  45. /* debug control panel constants */
  46. #define    BUG_OFF        100    /* debug inactive */
  47. #define    BUG_ON        101    /* debug active */
  48. #define    BUG_COUNT    102    /* count debug events */
  49. #define    BUG_DISPLAY    103    /* display debug events */
  50. #define    BUG_FILTER    104    /* filter debug events */
  51. #define    BUG_FILTERLIST    105    /* debug filter list */
  52. #define    BUG_LOG        106    /* log debug events */
  53. #define    BUG_LOGFILE    107    /* debug log file */
  54. #define    BUG_OK        108    /* OK button */
  55. #define    BUG_CANCEL    109    /* CANCEL button */
  56.  
  57. /* default dialog box definitions */
  58. #define    DEF_BUTTON    (BS_DEFPUSHBUTTON|WS_TABSTOP|WS_CHILD)
  59.  
  60. /* standard dialog box definitions */
  61. #define    STD_FRAME    (SS_BLACKFRAME|WS_CHILD)
  62. #define    STD_CHECKBOX    (BS_CHECKBOX|WS_TABSTOP|WS_CHILD)
  63. #define    STD_BUTTON    (BS_PUSHBUTTON|WS_TABSTOP|WS_CHILD)
  64. #define    STD_RADIO    (BS_RADIOBUTTON|WS_TABSTOP|WS_CHILD)
  65. #define    STD_EDITFIELD    (WS_BORDER|WS_TABSTOP|WS_CHILD|
  66.                 ES_AUTOHSCROLL)
  67.  
  68. /* debug function definitions */
  69. BOOL FAR          Debug();
  70. BOOL FAR PASCAL DebugControl( HWND );
  71. BOOL FAR PASCAL DebugSetup( HWND, WORD, WORD );
  72. BOOL FAR PASCAL DebugControlDlgFn( HWND, WORD, WORD, LONG );
  73.  
  74.  
  75.  
  76. ==============================================================================
  77.  
  78.  
  79.  
  80. /*
  81.  * WINDOWS 2.00 DEBUG UTILITY - SOURCE CODE (DEBUG.C)
  82.  *
  83.  * LANGUAGE : microsoft C 5.0
  84.  * MODEL    : small or medium
  85.  * STATUS   : operational
  86.  *
  87.  * 12/11/87 1.00 - Kevin P. Welch - initial creation.
  88.  *
  89.  */
  90.  
  91. #include <windows.h>
  92. #include <string.h>
  93. #include <fcntl.h>
  94. #include <types.h>
  95. #include <stat.h>
  96. #include "debug.h"
  97.  
  98. /* internal macros */
  99. #define    TOGGLE(x,y)    CheckDlgButton(x,y,!IsDlgButtonChecked(x,y))
  100. #define    ENABLE(x,y,z)    EnableWindow(GetDlgItem(x,y),z)
  101.  
  102. /* general definitions */
  103. #define    SHARED        S_IREAD|S_IWRITE
  104. #define    MODE_APPEND    O_RDWR|O_APPEND|O_BINARY    
  105. #define    MODE_CREATE    O_RDWR|O_CREAT|O_BINARY
  106.  
  107. /* listbox viewport definitions */
  108. #define    PORT_X        20    /* viewport x origin */
  109. #define    PORT_Y        40    /* viewport y origin */
  110. #define    PORT_WIDTH    460    /* viewport width */
  111. #define    PORT_HEIGHT    140    /* viewport height */
  112.  
  113. /* debug statement data structure */
  114. #define    MAX_FILTER    32    /* maximum filter categories */
  115.  
  116. typedef struct {
  117.  
  118.     /* general options */
  119.     BOOL    bSetup;        /* debug setup flag */
  120.     BOOL    bActive;    /* debug active flag */
  121.     
  122.     /* count options */
  123.     BOOL    bCount;        /* count events flag */
  124.     LONG    lMsgCount;    /* debug message count */
  125.  
  126.     /* display options */
  127.     BOOL    bDisplay;    /* display debug events */
  128.     HWND    hListBox;    /* listbox window handle */
  129.     WORD    wEntries;    /* current listbox lines */
  130.     WORD    wMaxEntries;    /* maximum listbox lines */
  131.     
  132.     /* filter options */
  133.     BOOL    bFilter;    /* filter debug events */
  134.     WORD    wFilterSize;    /* size of categories */
  135.     WORD    Filter[MAX_FILTER];    /* list of categories */
  136.  
  137.     /* log-file options */
  138.     BOOL    bLog;        /* log debug events */
  139.     char    szLogFile[64];    /* debug log file name */
  140.  
  141. } OPTIONS;
  142.  
  143. /* global data definitions */
  144. static OPTIONS    Options;    
  145.  
  146. /*
  147.  * DebugSetup( hWnd, wMsg, wMax ) : bResult
  148.  *
  149.  *    hWnd    main application window handle
  150.  *    wMsg    debug control panel system message
  151.  *    wMax    maximum number of debug lines
  152.  *
  153.  * This function is responsible for creating the debug viewport
  154.  * window class and for attaching the control panel to the system
  155.  * menu of the window handle provided (this implies that the window
  156.  * handle provided has a system menu).
  157.  *
  158.  * A boolean value of TRUE is returned if the setup process was
  159.  * successful.
  160.  *
  161.  */
  162.  
  163. BOOL FAR PASCAL DebugSetup( hWnd, wMsg, wMax )
  164.     HWND    hWnd;
  165.     WORD    wMsg;
  166.     WORD    wMax;
  167. {
  168.     /* local variables */
  169.     BOOL        bOk;        /* boolean result */
  170.     HMENU        hSysMenu;    /* temporary menu handle */
  171.     WNDCLASS    WndClass;    /* temporary class 
  172.                         structure */
  173.     HANDLE        hInstance;    /* handle to window 
  174.                         instance */
  175.     char        szModule[64];    /* main module file name */
  176.     
  177.     /* boolean result */
  178.     bOk = FALSE;
  179.     hInstance = GetWindowWord( hWnd, GWW_HINSTANCE );
  180.     
  181.     /* check if debug already activated */
  182.     if ( !Options.bSetup ) {
  183.  
  184.         /* retrieve system menu handle */
  185.         hSysMenu = GetSystemMenu( hWnd, FALSE );
  186.         if ( hSysMenu ) {
  187.         
  188.             /* change system menu to reflect control panel */
  189.             ChangeMenu( hSysMenu, 0, NULL, 999, 
  190.                     MF_APPEND|MF_SEPARATOR );
  191.             ChangeMenu( hSysMenu, 0, "&Debug...", wMsg, 
  192.                     MF_APPEND|MF_STRING);
  193.     
  194.             /* create listbox window -initially hidden */
  195.             Options.hListBox = CreateWindow(
  196.                     "LISTBOX",        /* class name */
  197.                     "",                /* window caption */
  198.                     WS_BORDER|WS_VSCROLL,    /* window style */
  199.                     PORT_X,            /* x position */
  200.                     PORT_Y,            /* y position */
  201.                     PORT_WIDTH,        /* width */
  202.                     PORT_HEIGHT,    /* height */
  203.                     NULL,            /* parent window */
  204.                     NULL,            /* menu */
  205.                     hInstance,        /* instance handle */
  206.                     (LPSTR)NULL        /* other data */
  207.                 );
  208.                     
  209.             /* continue if successful */
  210.             if ( Options.hListBox ) {
  211.                                 
  212.                 /* define options data */
  213.                 bOk = TRUE;
  214.                 Options.bSetup = TRUE;
  215.                 Options.wMaxEntries = wMax;
  216.  
  217.                 /* define default log file name */
  218.                 GetModuleFileName( hInstance, szModule, 
  219.                                     sizeof(szModule) );
  220.                     
  221.                 *strrchr(szModule,'.') = 0;
  222.                 sprintf(
  223.                     Options.szLogFile,
  224.                     "%s.LOG",
  225.                     (char *)(strrchr(szModule,'\\')+1)
  226.                 );
  227.  
  228.             }
  229.         
  230.         } 
  231.  
  232.     } 
  233.  
  234.     /* return final result */
  235.     return( bOk );
  236.  
  237. }
  238.  
  239. /*
  240.  * DebugControl( hWnd ) : BOOL FAR PASCAL
  241.  *
  242.  *        hWnd    main application window handle
  243.  *
  244.  * This function enables the user to monitor and adjust the debug
  245.  * control panel settings.  When this function is called a modal
  246.  * dialog box is displayed which allows the user to set the
  247.  * debug options.
  248.  *
  249.  * The value returned indicates how the user terminated the
  250.  * dialog box - TRUE implies the OK button was pressed, FALSE
  251.  * the CANCEL button.
  252.  *
  253.  */
  254.  
  255. BOOL FAR PASCAL DebugControl( hWnd )
  256.     HWND        hWnd;
  257. {
  258.     /* local variables */
  259.     FARPROC        lpProc;            /* temporary function address */
  260.     BOOL        bResult;        /* boolean result value */
  261.     HANDLE        hInstance;        /* window instance handle */
  262.  
  263.     /* retrieve instance handle */
  264.     hInstance = GetWindowWord( hWnd, GWW_HINSTANCE );
  265.     
  266.     /* display dialog box */
  267.     lpProc = MakeProcInstance( DebugControlDlgFn, hInstance );
  268.     bResult = DialogBox(hInstance,(LPSTR)"DebugControl",hWnd,lpProc);
  269.     FreeProcInstance( lpProc );
  270.  
  271.     /* return final result */
  272.     return( bResult );
  273.  
  274. }
  275.  
  276. /*
  277.  * DebugControlDlgFn( hDlg, wMsg, wParam, lParam ) : BOOL FAR PASCAL
  278.  *
  279.  *        hDlg        window handle
  280.  *        wMsg        dialog message
  281.  *        wParam        word parameter
  282.  *        lParam        long parameter
  283.  *
  284.  * This function processes all the messages related to the
  285.  * debug control panel dialog box.  With the dialog box the
  286.  * user can add, change, and remove debugging channels.
  287.  *
  288.  */
  289.  
  290. BOOL FAR PASCAL DebugControlDlgFn( hDlg, wMsg, wParam, lParam )
  291.     HWND        hDlg;
  292.     WORD        wMsg;
  293.     WORD        wParam;
  294.     LONG        lParam;
  295. {
  296.     /* local variables */
  297.     BOOL        bResult;    /* boolean result variable */
  298.     
  299.     /* initialization */
  300.     bResult = TRUE;
  301.  
  302.     /* process message */
  303.     switch( wMsg )
  304.         {
  305.     case WM_INITDIALOG :    /* initialize dialog box */
  306.         
  307.         {
  308.             /* local variables */
  309.             WORD    i;            /* loop variable */
  310.             int        xPopup;        /* popup x position */
  311.             int        yPopup;        /* popup y position */
  312.             int        cxPopup;    /* width of popup window */
  313.             int        cyPopup;    /* height of popup window */
  314.             RECT    rectWnd;    /* temporary window rect */
  315.             char    szToken[8];    /* character token */
  316.             char    szFilterList[64];    /* filter list string */
  317.             
  318.             /* The following code centers the dialog box in the
  319.              * middle of the screen.  It uses the dimensions of 
  320.              * the display and the dialog box and repositions the
  321.              * dialog box accordingly.
  322.              */
  323.             
  324.             /* retrieve popup rectangle  */
  325.             GetWindowRect( hDlg, (LPRECT)&rectWnd );
  326.             
  327.             /* calculate popup extents */
  328.             cxPopup = rectWnd.right - rectWnd.left;
  329.             cyPopup = rectWnd.bottom - rectWnd.top;
  330.     
  331.             /* calculate new location & move dialog box */
  332.             xPopup = ( GetSystemMetrics(SM_CXSCREEN) - cxPopup) / 2;
  333.             yPopup = ( GetSystemMetrics(SM_CYSCREEN) - cyPopup) / 2;
  334.             
  335.             MoveWindow( hDlg, xPopup, yPopup, cxPopup, cyPopup, TRUE);
  336.  
  337.             /* define filter list */
  338.             szFilterList[0] = 0;
  339.             if ( Options.wFilterSize ) {
  340.                 sprintf( szFilterList, "%u", Options.Filter[0] );
  341.                 for ( i=1; i<Options.wFilterSize; i++ ) {
  342.                     sprintf( szToken, ",%u", Options.Filter[i] );
  343.                     strcat( szFilterList, szToken );
  344.                 }
  345.             }
  346.             
  347.             /* check ON-OFF radio buttons */
  348.             CheckRadioButton(
  349.                 hDlg, 
  350.                 BUG_OFF, 
  351.                 BUG_ON, 
  352.                 (Options.bActive) ? BUG_ON :BUG_OFF
  353.             );
  354.         
  355.             /* define check boxes */
  356.             CheckDlgButton( hDlg, BUG_COUNT, Options.bCount );
  357.             CheckDlgButton( hDlg, BUG_DISPLAY, Options.bDisplay );
  358.             CheckDlgButton( hDlg, BUG_FILTER, Options.bFilter );
  359.             CheckDlgButton( hDlg, BUG_LOG, Options.bLog );
  360.     
  361.             /* display filter categories & log file name */
  362.             SetDlgItemText( hDlg, BUG_FILTERLIST, szFilterList );
  363.             SetDlgItemText( hDlg, BUG_LOGFILE, Options.szLogFile );
  364.         
  365.             /* disable check boxes & edit fields if debug inactive */
  366.             if ( !Options.bActive ) {
  367.  
  368.                 /* disable check boxes */
  369.                 ENABLE( hDlg, BUG_COUNT, FALSE );
  370.                 ENABLE( hDlg, BUG_DISPLAY, FALSE );
  371.                 ENABLE( hDlg, BUG_FILTER, FALSE );
  372.                 ENABLE( hDlg, BUG_LOG, FALSE );
  373.     
  374.                 /* disable edit fields */
  375.                 ENABLE( hDlg, BUG_FILTERLIST, FALSE );
  376.                 ENABLE( hDlg, BUG_LOGFILE, FALSE );
  377.     
  378.             } else {
  379.         
  380.                 /* enable edits field */
  381.                 ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  382.                         BUG_FILTER) );
  383.                 ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  384.                         BUG_LOG) );
  385.         
  386.             }
  387.         
  388.         }
  389.                 
  390.         break;
  391.     case WM_COMMAND : /* dialog box command */
  392.  
  393.         /* process sub-message */
  394.         switch( wParam )
  395.             {
  396.         case BUG_ON : /* turn debug on */
  397.             
  398.             /* redefine radio button */
  399.             CheckRadioButton( hDlg, BUG_OFF, BUG_ON, BUG_ON );
  400.             
  401.             /* enable check boxes */
  402.             ENABLE( hDlg, BUG_COUNT, TRUE );
  403.             ENABLE( hDlg, BUG_DISPLAY, TRUE );
  404.             ENABLE( hDlg, BUG_FILTER, TRUE );
  405.             ENABLE( hDlg, BUG_LOG, TRUE );
  406.             
  407.             /* enable edits field */
  408.             ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  409.                     BUG_FILTER) );
  410.             ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  411.                     BUG_LOG) );
  412.                 
  413.             break;
  414.         case BUG_OFF : /* turn debug off */
  415.             
  416.             /* redefine radio button */
  417.             CheckRadioButton( hDlg, BUG_OFF, BUG_ON, BUG_OFF );
  418.             
  419.             /* enable check boxes */
  420.             ENABLE( hDlg, BUG_COUNT, FALSE );
  421.             ENABLE( hDlg, BUG_DISPLAY, FALSE );
  422.             ENABLE( hDlg, BUG_FILTER, FALSE );
  423.             ENABLE( hDlg, BUG_LOG, FALSE );
  424.             
  425.             /* enable edit fields */
  426.             ENABLE( hDlg, BUG_FILTERLIST, FALSE );
  427.             ENABLE( hDlg, BUG_LOGFILE, FALSE );
  428.             
  429.             break;
  430.         case BUG_COUNT : /* count debug events */
  431.             TOGGLE( hDlg, BUG_COUNT );                        
  432.             break;
  433.         case BUG_DISPLAY : /* display debug events */
  434.             TOGGLE( hDlg, BUG_DISPLAY );
  435.             break;
  436.         case BUG_FILTER : /* filter debug events */
  437.             TOGGLE( hDlg, BUG_FILTER );
  438.             ENABLE( hDlg, BUG_FILTERLIST, IsDlgButtonChecked(hDlg,
  439.                     BUG_FILTER) );
  440.             break;
  441.         case BUG_LOG : /* log debug events */
  442.             TOGGLE( hDlg, BUG_LOG );
  443.             ENABLE( hDlg, BUG_LOGFILE, IsDlgButtonChecked(hDlg,
  444.                     BUG_LOG) );
  445.             break;
  446.         case BUG_OK : /* done with debug control panel */
  447.             
  448.             {
  449.                 /* local variables */
  450.                 WORD        i;
  451.                 char *        spToken;
  452.                 char        szToken[8];
  453.                 char        szCaption[64];
  454.                 char        szFilterList[32];
  455.  
  456.                 /* capture radio button state */
  457.                 Options.bActive = IsDlgButtonChecked( hDlg, BUG_ON );
  458.             
  459.                 /* capture check box states */
  460.                 Options.bCount = IsDlgButtonChecked( hDlg, BUG_COUNT);
  461.                 Options.bDisplay=IsDlgButtonChecked(hDlg,BUG_DISPLAY);
  462.                 Options.bFilter=IsDlgButtonChecked( hDlg,BUG_FILTER);
  463.                 Options.bLog = IsDlgButtonChecked( hDlg, BUG_LOG );
  464.  
  465.                 /* capture filter list changes - no limit checking! */
  466.                 GetDlgItemText(
  467.                     hDlg,
  468.                     BUG_FILTERLIST,
  469.                     szFilterList,
  470.                     sizeof(szFilterList)
  471.                 );
  472.             
  473.                 Options.wFilterSize = 0;
  474.                 spToken = strtok( szFilterList, " ,;" );
  475.                 while ( spToken ) {
  476.                     Options.Filter[ Options.wFilterSize++ ] = 
  477.                                                     atoi( spToken );
  478.                     spToken = strtok( NULL, " ,;" );
  479.                 }
  480.                     
  481.                 /* capture log file changes */
  482.                 GetDlgItemText(
  483.                     hDlg,
  484.                     BUG_LOGFILE,
  485.                     Options.szLogFile,
  486.                     sizeof(Options.szLogFile)
  487.                 );
  488.             
  489.                 /* display listbox if necessary */
  490.                 if ( Options.bActive ) {
  491.  
  492.             
  493.                     /* update viewport window caption */
  494.                     if ( Options.bFilter && Options.wFilterSize ) {
  495.                         
  496.                         /* define filter list */
  497.                         szFilterList[0] = 0;
  498.                         if ( Options.wFilterSize ) {
  499.                             sprintf( szFilterList, "%u", 
  500.                                         Options.Filter[0] );
  501.                             for ( i=1; i<Options.wFilterSize; i++ ) {
  502.                                 sprintf( szToken, ",%u", 
  503.                                         Options.Filter[i] );
  504.                                 strcat( szFilterList, szToken );
  505.                             }
  506.                         }    
  507.                         
  508.                         sprintf( 
  509.                             szCaption, 
  510.                             "%s - (%s)", 
  511.                             Options.szLogFile, 
  512.                             szFilterList 
  513.                         );
  514.                     
  515.                     } else
  516.                         sprintf( szCaption, "%s - (ALL)", 
  517.                                     Options.szLogFile );
  518.                     
  519.                     /* define caption & make window visible */
  520.                     SetWindowText( Options.hListBox, szCaption );
  521.                     ShowWindow( Options.hListBox, SHOW_OPENWINDOW );
  522.                     
  523.                 } else
  524.                     ShowWindow( Options.hListBox, HIDE_WINDOW );
  525.                 
  526.                 /* exit */
  527.                 EndDialog( hDlg, TRUE );
  528.             
  529.             }
  530.             
  531.             break;
  532.         case BUG_CANCEL :    /* cancel control panel */
  533.         case IDCANCEL :
  534.             EndDialog( hDlg, FALSE );
  535.             break;
  536.         default :            /* ignore all others */
  537.             bResult = FALSE;
  538.             break;
  539.         }
  540.         
  541.         break;
  542.     default :
  543.         bResult = FALSE;
  544.         break;
  545.     }
  546.  
  547.     /* return final result */
  548.     return( bResult );
  549.  
  550. }
  551.  
  552. /*
  553.  * Debug( wCategory, ParmList) : BOOL FAR
  554.  *
  555.  *        wCategory        debug message classification
  556.  *        ParmList        debug parameter list
  557.  *
  558.  * This function outputs a formatted message to the debug
  559.  * utility routines.  The wCategory variable determines 
  560.  * how the message is filtered.  The ParmList is a standard
  561.  * printf parameter list.  A value of TRUE is returned if
  562.  * the message was successfully processed and not filtered.
  563.  *
  564.  * Note that this function CANNOT be declared of type
  565.  * PASCAL as it uses a variable number of arguments!  Also
  566.  * note that alternative methods are available for handling
  567.  * a variable number of function parameters.
  568.  *
  569.  */
  570.  
  571. BOOL FAR Debug( wCategory, ParmList )
  572.     WORD        wCategory;
  573.     struct {
  574.         char    cBytes[64];
  575.     } ParmList;
  576. {
  577.     /* local variables */
  578.     WORD        i;                    /* temporary loop variable */
  579.     int            hFile;                /* log file handle */
  580.     BOOL        bResult;            /* result of function */
  581.     BOOL        bInclude;            /* include message flag */
  582.     char        szStatement[132];    /* temporary statement */
  583.  
  584.     /* initialization */
  585.     bResult = FALSE;
  586.  
  587.     /* process statement if debug active */
  588.     if ( Options.bSetup && Options.bActive ) {
  589.     
  590.         bInclude = TRUE;
  591.  
  592.         /* check for inclusion in filter list */
  593.         if ( Options.bFilter ) {
  594.             
  595.             /* search filter list */
  596.             for (
  597.                 i=0; 
  598.                 (i<Options.wFilterSize)&&(Options.Filter[i]!=
  599.                                                         wCategory); 
  600.                 i++ 
  601.             );
  602.         
  603.             /* turn off include if not found */
  604.             if ( i >= Options.wFilterSize )
  605.                 bInclude = FALSE;
  606.         
  607.         }
  608.         
  609.         /* format debug statement if included */
  610.         if ( bInclude ) {
  611.         
  612.             /* prepare for debug statement */
  613.             i = 0;
  614.             bResult = TRUE;
  615.             Options.lMsgCount++;
  616.             
  617.             /* define debug statement */
  618.             if ( Options.bCount ) 
  619.                 i = sprintf( szStatement, "%ld ", Options.lMsgCount );
  620.             i += sprintf( &szStatement[i], ParmList );
  621.                 
  622.             /* display debug statement in listbox */
  623.             if ( Options.bDisplay ) {            
  624.                 
  625.                 /* Note: since we are passing the formatted
  626.                  * debugging statement to the listbox using
  627.                  * a SendMessage we cannot do anything which
  628.                  * would cause memory to be shuffled - this
  629.                  * invalidates the pointer!
  630.                  */
  631.                 
  632.                 /* add new statement to listbox */
  633.                 SendMessage(
  634.                     Options.hListBox,
  635.                     LB_ADDSTRING,
  636.                     (WORD)0,
  637.                     (LONG)(LPSTR)szStatement
  638.                 );
  639.                         
  640.                 /* remove first statement from listbox if necessary */
  641.                 if ( Options.wEntries >= Options.wMaxEntries ) {
  642.                     SendMessage(
  643.                         Options.hListBox,
  644.                         LB_DELETESTRING,
  645.                         0,
  646.                         (LONG)0
  647.                     );
  648.                 } else
  649.                     Options.wEntries++; 
  650.             
  651.                 /* make last statement visible */
  652.                 SendMessage(
  653.                     Options.hListBox,
  654.                     LB_SETCURSEL,
  655.                     (WORD)Options.wEntries-1,
  656.                     (LONG)0
  657.                 );
  658.  
  659.             }
  660.             
  661.             /* output debug statement to logfile */
  662.             if ( Options.bLog ) {
  663.             
  664.                 /* open or create log file */
  665.                 hFile = open( Options.szLogFile, MODE_APPEND, SHARED);
  666.                 if ( hFile < 0 )
  667.                     hFile=open(Options.szLogFile,MODE_CREATE,SHARED);
  668.                     
  669.                 /* write message to file if sucessful */
  670.                 if ( hFile > 0 ) {
  671.                     write( hFile, szStatement, i );
  672.                     write( hFile, "\r\n", 2 );
  673.                     close( hFile );
  674.                 } 
  675.             
  676.             }
  677.         
  678.         } 
  679.     
  680.     } 
  681.     
  682.     /* return result */
  683.     return( bResult );
  684.  
  685. }    
  686.  
  687.  
  688.  
  689.  
  690. Figure 8
  691. ========
  692.  
  693.  
  694. BUGTEST MAKE File
  695. =================
  696.  
  697.  
  698. STDFLAGS=-c -u -AS -FPa -Gsw -Os -Zep
  699. BUGFLAGS=-c -u -AS -FPa -Gsw -Os -Zep -DDEBUG
  700.  
  701. bugtest.res: bugtest.rc bugtest.ico
  702.    rc -r bugtest.rc
  703.  
  704. debug.obj: debug.h debug.c
  705.    cl $(STDFLAGS) debug.c
  706.  
  707. bugtest.obj: bugtest.c
  708.    cl $(BUGFLAGS) bugtest.c
  709.  
  710. bugtest.exe: bugtest.obj bugtest.def bugtest.res debug.obj
  711.    link4 bugtest+debug /AL:16 /NOE,,,slibw,bugtest.def
  712.    rc bugtest.res
  713.  
  714.  
  715. ==============================================================================
  716.  
  717.  
  718. /*
  719.  * DEBUG TEST PROGRAM - SOURCE CODE (BUGTEST.C)
  720.  *
  721.  * LANGUAGE : Microsoft C 5.0
  722.  * MODEL    : small
  723.  * STATUS   : operational
  724.  *
  725.  * 12/11/87 1.00 - Kevin P. Welch - initial creation.
  726.  *
  727.  */
  728.  
  729. #include <windows.h>
  730. #include "debug.h"
  731.  
  732. /* local definitions */
  733. #define    BUG_CONTROL    201
  734.  
  735. /* function definitions */
  736. LONG FAR PASCAL    TestWndFn( HWND, WORD, WORD, LONG );
  737.  
  738. /* */
  739.  
  740. /*
  741.  * MAINLINE - BUG TEST PROGRAM
  742.  *
  743.  * This mainline initializes the test program and processes
  744.  * and dispatches all messages relating to the debug test
  745.  * window.
  746.  *
  747.  */
  748.  
  749. int PASCAL WinMain( hInstance, hPrevInstance, lpsCmd, wCmdShow )
  750.    HANDLE    hInstance;
  751.    HANDLE       hPrevInstance;
  752.    LPSTR        lpsCmd;
  753.    WORD          wCmdShow;
  754. {
  755.     /* local variables */
  756.    MSG        Msg;    /* current system message */
  757.      
  758.     /* initialization */
  759.     if ( TestInit( hInstance, hPrevInstance, lpsCmd, wCmdShow ) ) {
  760.  
  761.         /* process system messages until finished */
  762.         while ( GetMessage( (LPMSG)&Msg, NULL, 0, 0 ) ) {
  763.             TranslateMessage( (LPMSG)&Msg );
  764.             DispatchMessage( (LPMSG)&Msg );
  765.         }
  766.  
  767.         /* terminate application */
  768.         exit( Msg.wParam );
  769.             
  770.     } else
  771.         exit( FALSE );
  772.  
  773. }
  774.  
  775. /* */
  776.  
  777. /*
  778.  *    TestInit( hInstance, hPrevInstance, lpsCmd, wCmdShow ) : BOOL;
  779.  *
  780.  *        hInstance    current instance handle
  781.  *        hPrevInstance    handle to previous instance
  782.  *        lpsCmd        command line string
  783.  *        wCmdShow    window display flag
  784.  *
  785.  * This utility function performs all the initialization required
  786.  * for testing the debug utility.  Included in this program is
  787.  * the registry and creation of the main window & the installation
  788.  * of the debug utility code.
  789.  *
  790.  */
  791.  
  792. static BOOL TestInit( hInstance, hPrevInstance, lpsCmd, wCmdShow )
  793.     HANDLE        hInstance;
  794.     HANDLE        hPrevInstance;
  795.     LPSTR        lpsCmd;
  796.     WORD        wCmdShow;
  797. {
  798.     /* local variables */
  799.     HWND        hWnd;    /* current window handle */
  800.     BOOL        bResult;    /* result of initialization */
  801.     WNDCLASS    WndClass;    /* window class */
  802.  
  803.     /* initialization */
  804.     bResult = FALSE;
  805.     
  806.     /* register window class */
  807.     if ( !hPrevInstance ) {
  808.     
  809.         /* define MAZE window class */
  810.         memset( &WndClass, 0, sizeof(WNDCLASS) );
  811.         WndClass.lpszClassName = (LPSTR)"TestWindow";
  812.         WndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
  813.         WndClass.lpszMenuName = (LPSTR)NULL;
  814.         WndClass.style = CS_HREDRAW | CS_VREDRAW;
  815.         WndClass.lpfnWndProc = TestWndFn;
  816.         WndClass.hInstance = hInstance;
  817.         WndClass.hIcon = LoadIcon( hInstance, "BugTestIcon" );
  818.         WndClass.hbrBackground = (HBRUSH)(COLOR_MENU + 1);
  819.     
  820.         /* register maze window class */        
  821.         if ( RegisterClass( (LPWNDCLASS)&WndClass ) ) {
  822.     
  823.             /* create window */
  824.             hWnd = CreateWindow(
  825.                     "TestWindow",                        /* class name */
  826.                     "Debug Test Window",                /* caption */
  827.                     WS_TILEDWINDOW,                    /* style */
  828.                     CW_USEDEFAULT,                        /* x position */
  829.                     CW_USEDEFAULT,                        /* y position */
  830.                     CW_USEDEFAULT,                        /* width */
  831.                     CW_USEDEFAULT,                        /* height */
  832.                     (HWND)NULL,                            /* parent window */
  833.                     (HMENU)NULL,                        /* menu */
  834.                     hInstance,                            /* application */
  835.                     (LPSTR)NULL                            /* other data */
  836.                 );
  837.  
  838.             /* continue if successful */
  839.             if ( hWnd ) {
  840.                 
  841.                 /* Here is where the debug utility is installed
  842.                  * into the program.  A response message number
  843.                  * is provided along with the maximum number of
  844.                  * debug statements which will be maintained
  845.                  * by the listbox.  The larger this number, the
  846.                  * less global memory available for your 
  847.                  * application.
  848.                  */
  849. #if DEBUG    
  850.                 DebugSetup( hWnd, BUG_CONTROL, 100 );
  851. #endif
  852.  
  853.                 /* make window visible */
  854.                 bResult = TRUE;
  855.                 ShowWindow( hWnd, wCmdShow );                                            
  856.  
  857.             }  
  858.                     
  859.         } 
  860.         
  861.     }
  862.     
  863.     /* return result */
  864.     return( bResult );
  865.     
  866. }
  867.  
  868. /* */
  869.  
  870. /*
  871.  * TEST WINDOW MESSAGE PROCESSING PROCEDURE
  872.  *
  873.  * TestWndFn( hWnd, wMessage, wParam, lParam ) : LONG FAR PASCAL
  874.  *
  875.  *        hWnd        window handle
  876.  *        wMessage    message number
  877.  *        wParam        additional message information
  878.  *        lParam        additional message information
  879.  *
  880.  * This window function processes all the messages related to
  881.  * the debug test window.  Using the system menu the user can
  882.  * display the debug control panel dialog box.
  883.  *
  884.  */
  885.  
  886. LONG FAR PASCAL TestWndFn( hWnd, wMessage, wParam, lParam )
  887.     HWND        hWnd;
  888.     WORD        wMessage;
  889.     WORD        wParam;
  890.     LONG        lParam;
  891. {
  892.     /* local variables */
  893.     LONG        lResult;    /* result of message */
  894.  
  895.     /* initialization */
  896.     lResult = FALSE;
  897.     
  898. #if DEBUG
  899.     /* sample debugging output */
  900.     switch( wMessage )
  901.         {
  902.     case WM_MOVE :
  903.         Debug( 1, "WM_MOVE: [%u,%u]", HIWORD(lParam), 
  904.             LOWORD(lParam) );
  905.         break;
  906.     case WM_SIZE :
  907.         Debug( 1, "WM_SIZE: [%u,%u]", HIWORD(lParam), 
  908.             LOWORD(lParam) );
  909.         break;
  910.     case WM_CHAR :
  911.         Debug( 2, "WM_CHAR: [%c,%u]", wParam, wParam );
  912.         break;
  913.     case WM_ACTIVATE :
  914.         Debug( 3, "WM_ACTIVATE: %s", 
  915.             (wParam)?"activate":"inactivate" );
  916.         break;
  917.     case WM_ACTIVATEAPP :
  918.         Debug( 3, "WM_ACTIVATEAPP: %s", 
  919.             (wParam)?"activate":"inactivate" );
  920.         break;
  921.     case WM_PAINT :
  922.         Debug( 4, "WM_PAINT:" );
  923.         break;
  924.     default : 
  925.         break;
  926.     }
  927. #endif
  928.  
  929.     /* process each message */
  930.     switch( wMessage )
  931.         {
  932.     case WM_SYSCOMMAND : /* system command */
  933.  
  934.         /* In here you need to handle the special case where the
  935.          * user asks for the debug control panel to be displayed.
  936.          * To do so you need to trap the control panel response
  937.          * message you provided when installing the debug
  938.          * utility.
  939.          */
  940.  
  941.         /* process sub-message */
  942.         switch( wParam )
  943.             {
  944. #if DEBUG
  945.         case BUG_CONTROL : /* debug control panel */
  946.             DebugControl( hWnd );
  947.             break;
  948. #endif
  949.         default :
  950.             lResult = DefWindowProc( hWnd, wMessage, 
  951.                         wParam, lParam );
  952.             break;
  953.         }        
  954.         
  955.         break;
  956.     case WM_DESTROY :    /* destroy window */
  957.         PostQuitMessage( 0 );
  958.         break;
  959.     default : /* send to default */
  960.         lResult = DefWindowProc( hWnd, wMessage, wParam, 
  961.                     lParam );
  962.         break;
  963.     }
  964.     
  965.     /* return normal result */
  966.     return( lResult );
  967.  
  968. }
  969.  
  970.  
  971. ==============================================================================
  972.  
  973.  
  974. BUGTEST DEF FIle
  975. ================
  976.  
  977.  
  978. NAME        BUGTEST
  979.  
  980. DESCRIPTION    'Debug Test Utility'
  981.  
  982. STUB        '\BIN\WINSTUB.EXE'
  983.  
  984. CODE        MOVEABLE
  985. DATA        MOVEABLE MULTIPLE
  986.  
  987. HEAPSIZE    4096
  988. STACKSIZE    4096
  989.  
  990. EXPORTS            
  991.     TestWndFn        @1
  992.     DebugControlDlgFn    @2
  993.     
  994.  
  995. ==============================================================================
  996.  
  997.  
  998. /*
  999.  * DEBUG TEST PROGRAM - RESOURCE FILE
  1000.  *
  1001.  * LANGUAGE : Microsoft C 5.0
  1002.  * MODEL    : small
  1003.  * STATUS    : operational
  1004.  *
  1005.  * 12/11/87 1.00 - Kevin P. Welch - initial creation.
  1006.  *
  1007.  */
  1008.  
  1009. #include <style.h>
  1010. #include "debug.h"
  1011.  
  1012. BugTestIcon    ICON    bugtest.ico
  1013.  
  1014. DebugControl DIALOG LOADONCALL MOVEABLE DISCARDABLE 8, 20, 185, 81
  1015. CAPTION "Debug Control Panel"
  1016. STYLE WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_POPUP
  1017. BEGIN
  1018.    CONTROL "OFF - debug &inactive." BUG_OFF, "button", STD_RADIO, 5, 3, 130, 12
  1019.    CONTROL "ON  - debug &active." BUG_ON, "button", STD_RADIO, 5, 15, 128, 12
  1020.    CONTROL "&Count debug events." BUG_COUNT, "button", STD_CHECKBOX, 18, 26, 114, 12
  1021.    CONTROL "&Display in debug window." BUG_DISPLAY, "button", STD_CHECKBOX, 18, 38, 114, 12
  1022.    CONTROL "&Filter" BUG_FILTER, "button", STD_CHECKBOX, 18, 50, 34, 12
  1023.    CONTROL "" BUG_FILTERLIST, "edit", STD_EDITFIELD, 55, 50, 78, 12
  1024.    CONTROL "&Log to" BUG_LOG, "button", STD_CHECKBOX, 18, 62, 36, 12
  1025.    CONTROL "" BUG_LOGFILE, "edit", STD_EDITFIELD , 55, 63, 78, 12
  1026.    CONTROL "" -1, "static", STD_FRAME, 142, 0, 1, 81
  1027.    CONTROL "Ok" BUG_OK, "button", DEF_BUTTON, 148, 4, 32, 14
  1028.    CONTROL "Cancel" BUG_CANCEL, "button", STD_BUTTON, 148, 21, 32, 14
  1029. END
  1030.  
  1031.  
  1032.