home *** CD-ROM | disk | FTP | other *** search
/ Boston 2 / boston-2.iso / DOS / PROGRAM / C / TEMPLATE / TESTER.C < prev    next >
Text File  |  1993-12-01  |  18KB  |  469 lines

  1. /****************************************************************************
  2.  
  3.     PROGRAM: Tester.c
  4.  
  5.     PURPOSE: DLL that records and plays back test scripts for Windows
  6.              applications
  7.     FUNCTIONS:
  8.  
  9.              LibMain() - automatic initialization function that performs
  10.                          one-time start-up processing.
  11.              WEP()     - DLL termination function; performs DLL cleanup before
  12.                          it is unloaded.
  13.              Tester()  - saves instance handle and creates main window
  14.              JournalRecordHook()   - A WH_JOURNALRECORD system hook that records
  15.                          keyboard and mouse event messages from the
  16.                          system queue
  17.              JournalPlaybackHook() - A WH_JOURNALPLAYBACK system hook that plays
  18.                          back previously recorded messages
  19.  
  20. *******************************************************************************/
  21. #include <windows.h>
  22. #include "tester.h"
  23. #include "testinc.h"
  24.  
  25. static FARPROC          fnNextJrnlHookFunc = NULL;
  26. static GLOBALHANDLE     hMemTestScript = NULL;
  27. static TESTRESULT       HaltStatus = TEST_OK;
  28. static HWND             hWnd2Notify;
  29. static WORD             wMsgtoSend;
  30. static char             str[MAXNUMBUFFS*BUFFERSIZE];
  31. static char             strtemp[BUFFERSIZE];
  32. static LPSTR            lpTraceFileName = NULL;
  33. static OFSTRUCT         OfStruct;              /* information from OpenFile() */
  34. static HANDLE           hFile;
  35. static EVENTQSTAT       EventStats;
  36. static BOOL             TraceOn;
  37.  
  38. BOOL FAR  PASCAL LibMain(HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize,
  39.                          LPSTR lpszCmdLine)
  40. {
  41. /* if DLL data seg is MOVEABLE */
  42. if (cbHeapSize != 0)
  43.    UnlockData(0);
  44.  
  45. return(TRUE);           /* Initialization successful */
  46. }
  47.  
  48. int FAR PASCAL WEP(int nParameter)
  49. {
  50. if (nParameter == WEP_SYSTEM_EXIT)
  51.    return (1);
  52. else
  53.    if (nParameter == WEP_FREE_DLL)
  54.       /* DLL use count is zero.  Every application that had loaded the DLL
  55.       has freed it. */
  56.       return (1);
  57.    else
  58.       /* Undefined value.  Ignore it.*/
  59.       return (1);
  60. }
  61. /**************************************************************************
  62.  
  63.     ROUTINE: Tester.c
  64.  
  65.     PURPOSE: Routine that is called by MainWndProc that installs a
  66.              WH_JOURNALRECORD hook, and initiates the recording of events.
  67.              It also installs the WH_JOURNALPLAYBACK hook to playback these
  68.              pre-recorded events.
  69.  
  70. ***************************************************************************/
  71. TESTRESULT FAR PASCAL Tester(TESTMODE AutotestMode, HANDLE hMemEvents,
  72.                              HWND hWndtoNotify, WORD wMsg,
  73.                              BOOL TraceOnFlag, LPSTR lpFileName)
  74. {
  75.    TESTRESULT     TesterReturnCode = TEST_OK;
  76.    LPEVENTMSGMSG  lpEvent;
  77.    unsigned int   EventQIndex;
  78.  
  79.    switch (AutotestMode)
  80.       {
  81.       case IDD_STARTRECORD:
  82.          /* Save the hWnd to send any stop messages to  */
  83.          hWnd2Notify = hWndtoNotify;
  84.          wMsgtoSend = wMsg;
  85.          HaltStatus = TEST_OK;
  86.  
  87.          /* Allocate the memory to hold the test event queue */
  88.          hMemTestScript = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  89.                                       MAXEVENTQSIZE * sizeof(EVENTMSG));
  90.          if (hMemTestScript == NULL)
  91.             {
  92.             TesterReturnCode = TEST_NOMEMORY;
  93.             HaltStatus = TEST_NOMEMORY;
  94.             }
  95.          else
  96.             {
  97.             /* Initialize the event queue header  */
  98.             EventStats.wNumEvents = 0;
  99.             EventStats.wNumEventsPlayed = 0;
  100.             EventStats.dwStartPlaybackTime = 0;
  101.             EventStats.wTimebetEvents = 0;
  102.             EventStats.wPercentofTime = 0;
  103.             EventStats.wMemUtilized = 0;
  104.             EventStats.wNumEventsBypassed = 0;
  105.             EventStats.wNumIterationsPlayed = 0;
  106.  
  107.  
  108.             /* Start recording events              */
  109.             fnNextJrnlHookFunc = SetWindowsHook(WH_JOURNALRECORD,
  110.                                                (FARPROC)JournalRecordHook);
  111.             TesterReturnCode = TEST_OK;
  112.             }
  113.          break;
  114.  
  115.       case IDD_STOPRECORD:
  116.          if (hMemTestScript == NULL)
  117.             /*  Recording not made     */
  118.             TesterReturnCode = TEST_INACTIVE;
  119.          else
  120.            {
  121.            /*  Stop Recording Events  */
  122.  
  123.            UnhookWindowsHook(WH_JOURNALRECORD, (FARPROC)JournalRecordHook);
  124.            /*  Adjust the timing in the event chain according to the users
  125.            Request   */
  126.            lpEvent = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
  127.            if (TraceOnFlag)
  128.               {
  129.               TraceOn = TRUE;
  130.               lpTraceFileName = lpFileName;
  131.               /* Write out the recorded events to the trace file */
  132.               for (EventQIndex= 1; EventQIndex < EventStats.wNumEvents;
  133.                    EventQIndex++)
  134.                {
  135.                lpEvent[EventQIndex].time -= lpEvent[0].time;
  136.  
  137.                /* Write out the events to the tracefile    */
  138.                wsprintf(str,
  139.                "Recorded Event MSG %d= %d; paramL= %x; paramH= %x; time= %ld\n",
  140.                           EventQIndex, lpEvent[EventQIndex].message,
  141.                           lpEvent[EventQIndex].paramL,
  142.                           lpEvent[EventQIndex].paramH,
  143.                           lpEvent[EventQIndex].time);
  144.                WriteFile(lpTraceFileName, (LPSTR)&str);
  145.                }
  146.               }
  147.            else
  148.               {
  149.               TraceOn = FALSE;
  150.               lpTraceFileName = NULL;
  151.               }
  152.  
  153.            /* Don't wait to playback the first event    */
  154.            lpEvent[0].time = 0;
  155.            GlobalUnlock(hMemTestScript);
  156.            TesterReturnCode = TEST_OK;
  157.            /*  Signal to the Autotest app that recording has stopped   */
  158.            SendMessage(hWnd2Notify, wMsgtoSend, hMemTestScript, HaltStatus);
  159.            hMemTestScript = NULL;
  160.            }
  161.          break;
  162.  
  163.       case IDD_STARTPLAY:
  164.          /* Save the hWnd to send any stop messages to  */
  165.          hWnd2Notify = hWndtoNotify;
  166.          wMsgtoSend = wMsg;
  167.          HaltStatus = TEST_OK;
  168.          if (TraceOnFlag)
  169.             {
  170.             TraceOn = TRUE;
  171.             lpTraceFileName = lpFileName;
  172.             }
  173.          else
  174.             {
  175.             TraceOn = FALSE;
  176.             lpTraceFileName = NULL;
  177.             }
  178.  
  179.          EventStats.wNumIterations = GetProfileInt("autotest",
  180.                                                    "NumberofIterations", 2);
  181.          GetProfileString("autotest","FixedTimingFlag","TRUE",
  182.                           EventStats.FixedTiming, 5 );
  183.          if ((EventStats.FixedTiming[0] == 't') ||
  184.              (EventStats.FixedTiming[0] == 'T'))
  185.             EventStats.wTimebetEvents = GetProfileInt("autotest",
  186.                                                       "TimeBetEvents",55);
  187.          else
  188.             EventStats.wPercentofTime = GetProfileInt("autotest",
  189.                                                       "PercentRecordTime", 100);
  190.          EventStats.wNumEventstoBypass = GetProfileInt("autotest",
  191.                                                        "NumEventstoBypass", 5);
  192.          EventStats.wBufferSize = GetProfileInt("autotest","IOBufferSize", 300);
  193.          /* Do not allow a buffer size of less than one or
  194.             greater than 5*BUFFERSIZE */
  195.          if (EventStats.wBufferSize < 1)
  196.             EventStats.wBufferSize = 1;
  197.          else
  198.             if (EventStats.wBufferSize > (15*MAXNUMBUFFS))
  199.                EventStats.wBufferSize = 15*MAXNUMBUFFS;
  200.  
  201.          /* Initialize Event Message structure */
  202.          EventStats.wNumEventsBuffered = EventStats.wBufferSize;
  203.          EventStats.wNumEventsPlayed = 0;
  204.          EventStats.wNumIterationsPlayed = 0;
  205.          EventStats.wNumEventsBypassed = 0;
  206.  
  207.          if (TraceOn)
  208.             {
  209.             /* Write the parameters out to the playback trace file   */
  210.             wsprintf(str, "[autotest]\nNumberofIterations= %d\n",
  211.                      EventStats.wNumIterations);
  212.             WriteFile(lpTraceFileName, (LPSTR)&str);
  213.             wsprintf(str, "FixedTimingFlag= %s\n",
  214.                      (LPSTR)&EventStats.FixedTiming[0]);
  215.             WriteFile(lpTraceFileName, (LPSTR)&str);
  216.             wsprintf(str, "TimebetEvents= %d\n", EventStats.wTimebetEvents);
  217.             WriteFile(lpTraceFileName, (LPSTR)&str);
  218.             wsprintf(str, "PercentRecordTime= %d\n", EventStats.wPercentofTime);
  219.             WriteFile(lpTraceFileName, (LPSTR)&str);
  220.             wsprintf(str, "NumEventstoBypass= %d\n",
  221.                      EventStats.wNumEventstoBypass);
  222.             WriteFile(lpTraceFileName, (LPSTR)&str);
  223.             wsprintf(str, "IOBufferSize= %d\n", EventStats.wBufferSize);
  224.             WriteFile(lpTraceFileName, (LPSTR)&str);
  225.             }
  226.  
  227.          str[0] = NULL;
  228.          EventStats.wNumEventsPlayed = 0;
  229.          hMemTestScript = (GLOBALHANDLE)hMemEvents;
  230.          lpEvent = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
  231.  
  232.          /* Perform calculations on timings      */
  233.          for (EventQIndex= 1; EventQIndex < EventStats.wNumEvents;
  234.               EventQIndex++)
  235.             {
  236.             if ((EventStats.FixedTiming[0] == 't') ||
  237.                 (EventStats.FixedTiming[0] == 'T'))
  238.                lpEvent[EventQIndex].time = lpEvent[0].time + (EventQIndex *
  239.                                            EventStats.wTimebetEvents);
  240.             else
  241.                if (EventStats.wPercentofTime > 0)
  242.                   lpEvent[EventQIndex].time = (lpEvent[EventQIndex].time *
  243.                                                EventStats.wPercentofTime /100);
  244.                else
  245.                   lpEvent[EventQIndex].time = (lpEvent[EventQIndex].time *
  246.                                                1/100);
  247.             }
  248.  
  249.          /* if there are events to playback    */
  250.          if (EventStats.wNumEvents != 0)
  251.             {
  252.             /* Initialize time playback is starting     */
  253.             EventStats.dwStartPlaybackTime = GetTickCount();
  254.             GlobalUnlock(hMemTestScript);
  255.  
  256.             /* Start recording events           */
  257.             fnNextJrnlHookFunc = SetWindowsHook(WH_JOURNALPLAYBACK,
  258.                                                 (FARPROC)JournalPlaybackHook);
  259.             TesterReturnCode = TEST_OK;
  260.             }
  261.          else
  262.             TesterReturnCode = TEST_NOEVENTS;
  263.          break;
  264.  
  265.       case IDD_STOPPLAY:
  266.          UnhookWindowsHook(WH_JOURNALPLAYBACK,
  267.                            (FARPROC)JournalPlaybackHook);
  268.  
  269.          /*  Signal to the Autotest app that playback has stopped    */
  270.          SendMessage(hWnd2Notify, wMsgtoSend, hMemTestScript, HaltStatus);
  271.          hMemTestScript = NULL;
  272.          break;
  273.    }
  274.  
  275.    return (TesterReturnCode);
  276. }
  277.  
  278. DWORD FAR PASCAL JournalRecordHook (int nCode, WORD wParam,
  279.                                     LPEVENTMSGMSG lpEventMsg)
  280. {
  281. DWORD   dwReturnCode;
  282. LPEVENTMSGMSG   lpEventEntry;
  283. WORD            wNumEvents;
  284.  
  285.    switch (nCode)
  286.       {
  287.       case HC_ACTION:
  288.          /* Check if the number of events exceeds our limit of x'FFFF' */
  289.          wNumEvents  = EventStats.wNumEvents + 1;
  290.  
  291.          if (wNumEvents == MAXEVENTQSIZE)
  292.             {
  293.             /* Reached our limit; stop recording  */
  294.             HaltStatus = TEST_TOOMANYEVENTS;
  295.             Tester(IDD_STOPRECORD, 0, 0, 0, TraceOn, (LPSTR)NULL);
  296.             }
  297.          else
  298.             {
  299.             /*  Append the new event on to the end of the memory block */
  300.             lpEventEntry = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
  301.             lpEventEntry[EventStats.wNumEvents] = *lpEventMsg;
  302.             EventStats.wNumEvents++;
  303.             GlobalUnlock(hMemTestScript);
  304.             }
  305.          break;
  306.  
  307.       }
  308.  
  309.       dwReturnCode = DefHookProc(nCode, wParam, (LONG)lpEventMsg,
  310.                                 (FARPROC FAR *)&fnNextJrnlHookFunc);
  311.       return(dwReturnCode);
  312. }
  313.  
  314. DWORD FAR PASCAL JournalPlaybackHook (int nCode, WORD wParam,
  315.                                       LPEVENTMSGMSG lpEventMsg)
  316. {
  317. DWORD           dwReturnCode = 0;
  318. DWORD           dwDelta = 0;
  319. LPEVENTMSGMSG   lpEventEntry;
  320. WORD            wNumEvntsPlayed;
  321. DWORD           dwTempTime = 0;
  322. DWORD           dwFreeSpace = 0;
  323.  
  324.  
  325.    lpEventEntry = (LPEVENTMSGMSG)GlobalLock(hMemTestScript);
  326.    switch (nCode)
  327.       {
  328.       case HC_SKIP:
  329.          /* Test if user has pressed control break    */
  330.          if ((GetAsyncKeyState(VK_CONTROL) & 0x8001)
  331.             && (GetAsyncKeyState(VK_CANCEL) & 0x8001))
  332.             {
  333.             if (TraceOn)
  334.                WriteFile(lpTraceFileName, (LPSTR)&str);
  335.             Tester(IDD_STOPPLAY, (HANDLE)NULL, (HWND)NULL, 0, TraceOn,
  336.                    (LPSTR)NULL);
  337.             }
  338.          ++EventStats.wNumEventsPlayed;
  339.          if (EventStats.wNumEventsPlayed > EventStats.wNumEvents)
  340.             {
  341.             ++EventStats.wNumIterationsPlayed;
  342.             if (EventStats.wNumIterationsPlayed < EventStats.wNumIterations)
  343.                {
  344.                EventStats.wNumEventsPlayed = 0;
  345.                EventStats.dwStartPlaybackTime = GetTickCount();
  346.                }
  347.             else
  348.                {
  349.                if (TraceOn)
  350.                   WriteFile(lpTraceFileName, (LPSTR)&str);
  351.                Tester(IDD_STOPPLAY, (HANDLE)NULL, (HWND)NULL, 0, TraceOn,
  352.                       (LPSTR)NULL);
  353.                }
  354.             }
  355.          /* if Trace Mode is on then capture information to be written
  356.             out to the playback trace file */
  357.          if (TraceOn)
  358.             {
  359.             ++EventStats.wNumEventsBypassed;
  360.             if (EventStats.wNumEventsBypassed > EventStats.wNumEventstoBypass)
  361.                {
  362.                /* Write out data to trace file       */
  363.                dwFreeSpace = GetFreeSpace(GMEM_NOT_BANKED);
  364.  
  365.                --EventStats.wNumEventsBuffered;
  366.                /* Buffering required for file I/O    */
  367.                wsprintf(strtemp, "Iteration= %d, Event= %d, FreeSpace= %lu\n",
  368.                         EventStats.wNumIterationsPlayed,
  369.                         EventStats.wNumEventsPlayed, dwFreeSpace);
  370.                lstrcat((LPSTR)&str, (LPSTR)&strtemp);
  371.                if (EventStats.wNumEventsBuffered == 0)
  372.                   {
  373.                   WriteFile(lpTraceFileName, (LPSTR)&str);
  374.                   EventStats.wNumEventsBuffered = EventStats.wBufferSize;
  375.                   str[0] = NULL;
  376.                   }
  377.                EventStats.wNumEventsBypassed = 0;
  378.                }
  379.             }
  380.          break;
  381.  
  382.       case HC_GETNEXT:
  383.          /*  Copy the next event in the event queue into the EVENTMSG
  384.              structure     */
  385.          wNumEvntsPlayed = EventStats.wNumEventsPlayed;
  386.          *((LPEVENTMSGMSG)lpEventMsg) = lpEventEntry[wNumEvntsPlayed];
  387.  
  388.          /* Add time delta (Event'n' - Event0) back to Start Playing time   */
  389.          ((LPEVENTMSGMSG)lpEventMsg)->time += EventStats.dwStartPlaybackTime;
  390.  
  391.          /* All times are expressed in terms of elapsed time in millisecs since
  392.             system start We have used up some time doing all this processing */
  393.          dwReturnCode =  ((LPEVENTMSGMSG)lpEventMsg)->time - GetTickCount();
  394.  
  395.  
  396.          if ((signed long)dwReturnCode < 0)
  397.             dwReturnCode = 0;
  398.  
  399.          break;
  400.  
  401.       }
  402.  
  403.    GlobalUnlock(hMemTestScript);
  404.    dwReturnCode = DefHookProc(nCode, wParam, (LONG)lpEventMsg,
  405.                      (FARPROC FAR *)&fnNextJrnlHookFunc);
  406.    return(dwReturnCode);
  407. }
  408.  
  409. BOOL WriteFile(LPSTR lpWrFileName, LPSTR lpBuffer)
  410. {
  411. HANDLE   hFile;
  412. OFSTRUCT OfStruct;                /* information from OpenFile()     */
  413. WORD     wLength;
  414. char     wrstring[255];
  415.  
  416.    /* Check if file exists first    */
  417.    if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
  418.                                OF_READWRITE | OF_EXIST)))
  419.       {
  420.       /* Create it if it does not   */
  421.       if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
  422.                                   OF_CREATE | OF_PROMPT | OF_CANCEL)))
  423.          {
  424.          wsprintf(wrstring,
  425.                  "Tester; WriteFile; hWnd2Notify = %x; File %s not found",
  426.                   hWnd2Notify, lpWrFileName);
  427.          MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
  428.                     MB_OK | MB_ICONHAND);
  429.          return FALSE;
  430.          }
  431.       }
  432.    else
  433.       /* open the existing file   */
  434.       if (-1 == (hFile = OpenFile(lpWrFileName, (LPOFSTRUCT) &OfStruct,
  435.                                   OF_READWRITE | OF_REOPEN)))
  436.          {
  437.          wsprintf(wrstring,
  438.                  "WriteFile; hWnd2Notify = %x; Cannot reopen File %s to disk",
  439.                   hWnd2Notify, lpWrFileName);
  440.          MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
  441.                     MB_OK | MB_ICONHAND);
  442.          return FALSE;
  443.          }
  444.  
  445.       /* Make sure this writes out to the file OK           */
  446.       wLength = lstrlen(lpBuffer);
  447.  
  448.       /* Position the file pointer at the end of the file   */
  449.       _llseek(hFile, STARTPOSITION, ENDOFFILE);
  450.  
  451.       /* append string to end of file                       */
  452.       if (wLength != _lwrite(hFile, lpBuffer, wLength))
  453.          {
  454.          _lclose(hFile);
  455.          wsprintf(wrstring,
  456.                  "WriteFile; hWnd2Notify = %x;  Cannot write File %s to disk",
  457.                   hWnd2Notify, lpWrFileName);
  458.          MessageBox(hWnd2Notify, wrstring, "DEBUG", MB_APPLMODAL |
  459.                     MB_OK | MB_ICONHAND);
  460.          return FALSE;
  461.          }
  462.       else
  463.          {
  464.          _lclose(hFile);
  465.          }
  466.  
  467.   return TRUE;
  468. }
  469.