home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / msysjour / vol07 / 03 / debug / badapp.c < prev    next >
Text File  |  1992-05-01  |  13KB  |  430 lines

  1. #include <windows.h>
  2.  
  3. #include "badapp.h"
  4.  
  5. #define WINPROC        long FAR PASCAL
  6. #define MDIPROC        long FAR PASCAL
  7. #define DLGPROC        BOOL FAR PASCAL
  8. #define ENUMPROC       BOOL FAR PASCAL
  9. #define WINDOWS_PARAMS HWND hWnd, unsigned msg, WORD wParam, LONG lParam
  10. #define DIALOG_PARAMS  HWND hDlg, unsigned msg, WORD wParam, LONG lParam
  11. #define ENUM_PARAMS    HWND hWnd, LONG lParam
  12.  
  13. WINPROC WndProc ( WINDOWS_PARAMS );
  14. DLGPROC DlgProc ( WINDOWS_PARAMS );
  15. void AssertTrashedDS ( WORD wAssertValue );
  16. void InitializeDSSafeGuard( void );
  17.  
  18. /**************************************************************
  19. *                                                             *
  20. *                   Global Variables                          *
  21. *                                                             *
  22. **************************************************************/
  23.  
  24. #define UNDEF_ASSERT_VAR(p1) int p1;
  25. #define ASSERT_VAR(p1)       int p1=42;
  26.  
  27. // NOTE: Only UNINITIALIZED variables are arranged by the C compiler
  28. //       in the order you see them.  All pre-initialized variables,
  29. //       such as
  30. //
  31. //         int PremierSupport = 1;
  32. //
  33. //       are moved to a different area of the DS.
  34. //
  35. //
  36. // For these variables, you will want to init them immediately
  37. // using the InitializeDSSafeGaurd() function.
  38. //
  39.  
  40. UNDEF_ASSERT_VAR(asv1);
  41.                         HWND   ghWnd;
  42. UNDEF_ASSERT_VAR(asv2);
  43.                         HANDLE ghInst;
  44. UNDEF_ASSERT_VAR(asv3);
  45.                         char   szFullName[20];
  46. UNDEF_ASSERT_VAR(asv4);
  47.  
  48.  
  49. ASSERT_VAR(asv5);
  50.                         char   szAppName[]            = "BADAPP";
  51. ASSERT_VAR(asv6);
  52.                         char   szCaption[]            = "Buggy Windows App";
  53. ASSERT_VAR(asv7);
  54.                         char   szMenuName[]           = "PlainMenu";
  55. ASSERT_VAR(asv8);
  56.                         char   szDialogTemplateName[] = "MODALDIALOG";
  57. ASSERT_VAR(asv9);
  58.                         char   szSpace[]              = " ";
  59. ASSERT_VAR(asv10);
  60.                         char   szHello[]              = "Hello!";
  61. ASSERT_VAR(asv11);
  62.  
  63. /**************************************************************
  64. *                                                             *
  65. *              Assertion Tracking Defines                     *
  66. *                                                             *
  67. **************************************************************/
  68.  
  69. #define WinMain_Entry                       1
  70. #define WinMain_Exit                        2
  71. #define ModalDialog_Entry                   3
  72. #define ModalDialog_Exit                    4
  73. #define WndProc_WM_DESTROY                  5
  74. #define WndProc_WM_COMMAND_IDM_MODAL_Entry  6
  75. #define WndProc_WM_COMMAND_IDM_MODAL_Exit   7
  76. #define DlgProc_WM_COMMAND_IDOK_Entry       8
  77. #define DlgProc_WM_COMMAND_IDOK_Exit        9
  78. #define DlgProc_WM_COMMAND_IDCANCEL_Entry   10
  79. #define DlgProc_WM_COMMAND_IDCANCEL_Exit    11
  80.  
  81. /**************************************************************
  82. *                                                             *
  83. *                      WinMain                                *
  84. *                                                             *
  85. **************************************************************/
  86.  
  87. int PASCAL WinMain (HANDLE hInstance,  HANDLE hPrevInstance, 
  88.                     LPSTR lpszCmdLine, int    nCmdShow       )
  89. {
  90.   MSG         msg       ;
  91.   WNDCLASS    wndclass  ;
  92.  
  93.   InitializeDSSafeGuard();
  94.  
  95.   AssertTrashedDS ( WinMain_Entry );
  96.  
  97.   if (!hPrevInstance) 
  98.     {
  99.     wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT;
  100.     wndclass.lpfnWndProc   = WndProc ;
  101.     wndclass.cbClsExtra    = 0 ;
  102.     wndclass.cbWndExtra    = 0 ;
  103.     wndclass.hInstance     = hInstance ;
  104.     wndclass.hIcon         = NULL;
  105.     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
  106.     wndclass.hbrBackground = GetStockObject ( GRAY_BRUSH ) ;
  107.     wndclass.lpszMenuName  = (LPSTR)szMenuName ;
  108.     wndclass.lpszClassName = szAppName ;
  109.  
  110.     if (!RegisterClass (&wndclass))
  111.          return FALSE;
  112.     }
  113.  
  114.   ghInst = hInstance;
  115.  
  116.   ghWnd  = CreateWindow (szAppName, szCaption,
  117.                                WS_OVERLAPPEDWINDOW,
  118.                                100, 100,
  119.                                200, 200,
  120.                                NULL, NULL, hInstance, NULL) ;
  121.  
  122.   ShowWindow ( ghWnd, nCmdShow );
  123.   UpdateWindow ( ghWnd );
  124.  
  125.   while (GetMessage((LPMSG)&msg, NULL, 0, 0))
  126.     {
  127.     TranslateMessage(&msg);
  128.     DispatchMessage(&msg);
  129.     }
  130.  
  131.   AssertTrashedDS ( WinMain_Exit );
  132.  
  133.   return msg.wParam ;
  134. }
  135.  
  136. /*********************************************************************
  137. *                                                                    *
  138. *                  ModalDialog: Calls a Modal Dialog Box             *
  139. *                                                                    *
  140. *********************************************************************/
  141.  
  142. int ModalDialog ( LPSTR TemplateName, FARPROC FunctionName, LONG dwParam )
  143. {
  144.   FARPROC  lpDialogProc;
  145.   int      RetVal;
  146.  
  147.   AssertTrashedDS ( ModalDialog_Entry );
  148.  
  149.   lpDialogProc = MakeProcInstance ( FunctionName, ghInst );
  150.   RetVal       = DialogBoxParam ( ghInst, TemplateName, ghWnd, 
  151.                                   lpDialogProc, (DWORD)dwParam );
  152.   FreeProcInstance ( lpDialogProc );
  153.  
  154.   AssertTrashedDS ( ModalDialog_Exit );
  155.   
  156.   return RetVal;
  157. }
  158.  
  159. /*********************************************************************
  160. *                                                                    *
  161. *                       WndProc: Main Message Translator             *
  162. *                                                                    *
  163. *********************************************************************/
  164.  
  165. WINPROC WndProc ( WINDOWS_PARAMS )
  166. {
  167.   switch ( msg )
  168.     {
  169.     case WM_DESTROY :
  170.  
  171.       AssertTrashedDS ( WndProc_WM_DESTROY );
  172.  
  173.       PostQuitMessage (0) ;
  174.       break ;
  175.  
  176.     case WM_COMMAND :
  177.  
  178.       switch ( wParam )
  179.  
  180.         {
  181.         case IDM_MODAL :
  182.  
  183.            AssertTrashedDS ( WndProc_WM_COMMAND_IDM_MODAL_Entry );
  184.   
  185.            ModalDialog ( szDialogTemplateName, DlgProc, 0L );
  186.  
  187.            AssertTrashedDS ( WndProc_WM_COMMAND_IDM_MODAL_Exit  );
  188.   
  189.            break;
  190.  
  191.         default:
  192.  
  193.            return DefWindowProc ( hWnd, msg, wParam, lParam ) ;
  194.            break;
  195.         }
  196.  
  197.       break;
  198.  
  199.     default :
  200.  
  201.       return DefWindowProc ( hWnd, msg, wParam, lParam );
  202.  
  203.     }
  204.   return 0L ;
  205. }
  206.  
  207. /********************************************************************
  208. *                                                                   *
  209. *                  Vanilla Dialog Box Procedure                     *
  210. *                                                                   *
  211. ********************************************************************/
  212.  
  213. // Here is a typical dialog proc.  Most of these variables are not used,
  214. // but they are there in order to make the stack frame more resemble
  215. // a typical dialog proc.
  216.  
  217.  
  218. DLGPROC DlgProc ( DIALOG_PARAMS )
  219. {
  220.   int  iPositionOfComma;
  221.   char szBuffer[32];  
  222.  
  223.   switch (msg)
  224.     {
  225.     case WM_INITDIALOG:
  226.  
  227.        SetFocus ( GetDlgItem ( hDlg, IDD_NAME ));
  228.        return FALSE;
  229.  
  230.     case WM_COMMAND:
  231.       
  232.        switch (wParam)
  233.          {
  234.          case IDOK:
  235.  
  236.             AssertTrashedDS ( DlgProc_WM_COMMAND_IDOK_Entry );
  237.  
  238.             GetDlgItemText ( hDlg, IDD_NAME, szBuffer, sizeof(szBuffer) );
  239.  
  240.             // Step 1: Find the comma seperating the Last Name and the First Name
  241.             //         and then zero it out, effectively changing this one
  242.             //         string into two strings
  243.  
  244.             iPositionOfComma = lstrlen (szBuffer);
  245.             while (iPositionOfComma && (szBuffer[iPositionOfComma] != ',')) iPositionOfComma--;
  246.             szBuffer[iPositionOfComma] = 0;
  247.  
  248.             // Step 2: Copy the First name into the global buffer
  249.  
  250.             lstrcpy (szFullName, szBuffer+iPositionOfComma+1);
  251.  
  252.             // Step 3: Add a space
  253.  
  254.             lstrcat (szFullName, szSpace );
  255.  
  256.             // Step 4: Add the last name
  257.  
  258.             lstrcat (szFullName, szBuffer );
  259.  
  260.             // Step 5: Say Hi to the user
  261.  
  262.             MessageBox ( hDlg, szFullName, szHello, MB_OK );
  263.  
  264.             AssertTrashedDS ( DlgProc_WM_COMMAND_IDOK_Exit );
  265.  
  266.             break;
  267.  
  268.          case IDCANCEL:
  269.  
  270.             AssertTrashedDS ( DlgProc_WM_COMMAND_IDCANCEL_Entry );
  271.  
  272.             EndDialog ( hDlg, TRUE);          
  273.  
  274.             AssertTrashedDS ( DlgProc_WM_COMMAND_IDCANCEL_Exit );
  275.             return TRUE;
  276.         
  277.          default:
  278.           
  279.             return FALSE;
  280.          }
  281.        break;
  282.  
  283.     default:
  284.  
  285.        return FALSE;
  286.     }
  287.  
  288.   return TRUE;
  289. }
  290.  
  291. /**************************************************************
  292. *                                                             *
  293. *                      WinMain                                *
  294. *                                                             *
  295. **************************************************************/
  296.  
  297. #define CHECK(p1,p2)            \
  298. if (42 != p1)                   \
  299.   {                             \
  300.   if (!wBadVariable)            \
  301.     {                           \
  302.     wBadValue = p1;             \
  303.     p1 = 42;                    \
  304.     wBadVariable = p2;          \
  305.     }                           \
  306.   }
  307.  
  308. void AssertTrashedDS ( WORD wAssertValue )
  309. {
  310.   static WORD wQueueValue;   // The next open spot in the queue
  311.   static WORD wQueue[10];    // The actual queue
  312.  
  313.          WORD wBadVariable;
  314.          WORD wBadValue;
  315.  
  316.   //
  317.   // These three lines add the passed in AssertionValue into the queue,
  318.   // and zero out the next spot (which will be displayed as an asterisk)
  319.   //
  320.  
  321.   wQueue[wQueueValue] = wAssertValue;
  322.   wQueueValue = (wQueueValue+1)%10;
  323.   wQueue[wQueueValue] = 0;
  324.  
  325.   //
  326.   // The CHECK macro above will only set the wBadValue and wBadVariable
  327.   // values if no asserion violation has occured.  Since it is possible
  328.   // that multiple assertion variables could have been trashed at the
  329.   // same time, we will continue this loop as long as *any* of the
  330.   // assertion variables are trashed.  Note that the CHECK macro restores
  331.   // the trashed assertion varaible once it has detected it.  This
  332.   // prevents inifinite loops.
  333.   //
  334.  
  335.   do
  336.     {
  337.     // Resetting this varaible makes the assumption that no trashing was done
  338.  
  339.     wBadVariable = 0;
  340.  
  341.     //
  342.     // Check all of the variables.  Remember that once one trashing has been
  343.     // found, the remaining trashed varaibles will remain trashed.  The next
  344.     // iteration of the do-loop will find the next trashed variable, and
  345.     // so on until all trashed variables have been reported.
  346.     //
  347.  
  348.     CHECK(asv1,1);
  349.     CHECK(asv2,2);
  350.     CHECK(asv3,3);
  351.     CHECK(asv4,4);
  352.     CHECK(asv5,5);
  353.     CHECK(asv6,6);
  354.     CHECK(asv7,7);
  355.     CHECK(asv8,8);
  356.     CHECK(asv9,9);
  357.     CHECK(asv10,10);
  358.     CHECK(asv11,11);
  359.  
  360.     //
  361.     // If we actually found a trashing, report it
  362.     //
  363.  
  364.     if (wBadVariable)
  365.       {
  366.       int i;
  367.       char szMsg[255];
  368.       char szMsg1[255];
  369.       char szMsg2[128];
  370.       char szNum[10];
  371.  
  372.       // 
  373.       // Generate a string of the queue values, using a "*" for the zero
  374.       // value to indicate the end of the queue
  375.       //
  376.  
  377.       *szMsg1 = 0;
  378.       for ( i = 0; i < 10; i++ )
  379.         {
  380.         if (wQueue[i])
  381.           wsprintf ( szNum, "%d", wQueue[i]);
  382.         else
  383.           lstrcpy ( szNum, "*" );
  384.         if (i != 9)
  385.           lstrcat ( szNum, "," );
  386.         lstrcat ( szMsg1, szNum );
  387.         }
  388.  
  389.       //
  390.       // Create a cute string showing the programmer/unlucky enduser the list
  391.       //
  392.  
  393.       wsprintf ( szMsg, "%s (%s)",
  394.                  (LPSTR)"Assertion Failure",
  395.                  (LPSTR)szMsg1
  396.                );
  397.       
  398.       //
  399.       // Create a caption saying which varaible was trashed, and it's value
  400.       //
  401.  
  402.       wsprintf ( szMsg2, "Assertion Variable asv%d=%d", wBadVariable, wBadValue );
  403.  
  404.       //
  405.       // Alert the programmer/unlucky enduser
  406.       //
  407.  
  408.       MessageBox ( NULL, szMsg, szMsg2, MB_SYSTEMMODAL );
  409.  
  410.       }  // end if bad value
  411.     }
  412.   while (wBadVariable); // Keep doing this until assertion varaibles are clean
  413.  
  414. } // end function
  415.  
  416. /*********************************************************************
  417. *                                                                    *
  418. *                                                                    *
  419. *                                                                    *
  420. *********************************************************************/
  421.  
  422. void InitializeDSSafeGuard( void )
  423. {
  424.   asv1  = 42;
  425.   asv2  = 42;
  426.   asv3  = 42;
  427.   asv4  = 42;
  428. }
  429.  
  430.