home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / sd386v50.zip / sd386src.zip / ESPQ.C < prev    next >
Text File  |  1996-05-13  |  58KB  |  1,247 lines

  1. /*****************************************************************************/
  2. /* File:                                             IBM INTERNAL USE ONLY   */
  3. /*                                                                           */
  4. /*   espq.c                                                                  */
  5. /*                                                                           */
  6. /* Description:                                                              */
  7. /*                                                                           */
  8. /*   Queue handling for Esp.                                                 */
  9. /*                                                                           */
  10. /* History:                                                                  */
  11. /*                                                                           */
  12. /*   04/14/94 Created.                                                       */
  13. /*                                                                           */
  14. /*****************************************************************************/
  15.  
  16. #include "all.h"
  17.  
  18. static PSZ     EspQueBaseName = "\\QUEUES\\EspQue";
  19. static char    EspQueName[32];
  20. static BOOL    ReadQueReady;
  21. static BOOL    AllProbesAreDeadFlag;
  22. static int     RestartInstance = 0;
  23.  
  24. void    SetEspQueName( char *pQueName ) { strcpy(EspQueName, pQueName); }
  25. BOOL    AllProbesAreDead( void ) { return(AllProbesAreDeadFlag);}
  26. void    ResetAllProbesAreDeadFlag( void ) { AllProbesAreDeadFlag=FALSE;}
  27.  
  28. /*****************************************************************************/
  29. /* StartEspQue()                                                             */
  30. /*                                                                           */
  31. /* Description:                                                              */
  32. /*                                                                           */
  33. /*  Start up a que to handle esp messages.                                   */
  34. /*                                                                           */
  35. /* Parameters:                                                               */
  36. /*                                                                           */
  37. /* Return:                                                                   */
  38. /*                                                                           */
  39. /*    rc                                                                     */
  40. /*                                                                           */
  41. /* Assumptions:                                                              */
  42. /*                                                                           */
  43. /*****************************************************************************/
  44. APIRET StartEspQue( void )
  45. {
  46.  APIRET  rc;
  47.  char    PidString[12];
  48.  TIB    *pTib;
  49.  PIB    *pPib;
  50.  USHORT  ThisPid;
  51.  
  52.  /****************************************************************************/
  53.  /* - Get the pid of this probe and use it to define a unique name.          */
  54.  /* - Stuff in the base que name.                                            */
  55.  /* - Concatenate the pid to make the name unique for the system.            */
  56.  /****************************************************************************/
  57.  DosGetInfoBlocks(&pTib, &pPib);
  58.  ThisPid = (USHORT)pPib->pib_ulpid;
  59.  
  60.  memset(EspQueName, 0, sizeof(EspQueName));
  61.  strcat(EspQueName, EspQueBaseName);
  62.  
  63.  memset(PidString, 0, sizeof(PidString));
  64.  RestartInstance++;
  65.  sprintf( PidString, "%d-%d", ThisPid, RestartInstance );
  66.  strcat(EspQueName, PidString );
  67.  
  68.  /****************************************************************************/
  69.  /* - Set a flag to wait on indicating that the queue thread is ready to     */
  70.  /*   read.                                                                  */
  71.  /****************************************************************************/
  72.  ReadQueReady = FALSE;
  73.  
  74.  rc = StartQue(EspQueName, ReadEspQue);
  75.  if(rc) return(rc);
  76.  
  77.  /****************************************************************************/
  78.  /* - Also wait for the read queue thread to be started. In some cases,      */
  79.  /*   the DosStartSession() may cause the queue to be posted before(!)       */
  80.  /*   the queue thread gets started. So, we have to guarantee that this      */
  81.  /*   doesn't happen.                                                        */
  82.  /****************************************************************************/
  83.  while( ReadQueReady == FALSE ) DosSleep(100);
  84.  return( 0 );
  85. }
  86.  
  87. /*****************************************************************************/
  88. /* - Get the pointer to the EspQueName.                                      */
  89. /*****************************************************************************/
  90. PSZ GetEspQue( void )
  91. {
  92.  return(EspQueName);
  93. }
  94.  
  95. /*****************************************************************************/
  96. /* ReadEspQue()                                                              */
  97. /*                                                                           */
  98. /* Description:                                                              */
  99. /*                                                                           */
  100. /*   Read and handle the Esp queue messages. This function runs              */
  101. /*   in its own thread in a do forever loop.                                 */
  102. /*                                                                           */
  103. /* Parameters:                                                               */
  104. /*                                                                           */
  105. /*   pQueHandle     -> to the queue handle. This is passed in by the         */
  106. /*                     StartQue() function when the queue is created.        */
  107. /*                                                                           */
  108. /* Return:                                                                   */
  109. /*                                                                           */
  110. /*  void                                                                     */
  111. /*                                                                           */
  112. /* Assumptions:                                                              */
  113. /*                                                                           */
  114. /*****************************************************************************/
  115. void ReadEspQue( void *qHandle)
  116. {
  117.  REQUESTDATA  Request;
  118.  ULONG        DataLen;
  119.  BYTE         ElePri;
  120.  ULONG        EleCode;
  121.  USHORT       pid;
  122.  ULONG        sid;
  123.  ULONG        type;
  124.  USHORT       mte;
  125.  APIRET       rc;
  126.  BOOL         EndThread = FALSE;
  127.  BOOL         ParentStarted = FALSE;
  128.  LHANDLE      LsnHandle = 0;
  129.  ALLPIDS     *p;
  130.  BOOL         TorF;
  131.  LHANDLE      QueHandle;
  132.  BOOL         ParentTerminating = FALSE;
  133.  
  134.  ESP_QUE_ELEMENT *pDataAddr=NULL;
  135.  
  136.  if( IsVerbose() ) {printf("\nEsp Que Started");fflush(0);}
  137.  /****************************************************************************/
  138.  /* - The queue has its own handle for communications between itself and     */
  139.  /*   the dbg que.   When connected serially, then there is only one handle  */
  140.  /*   and it must be shared by all dbg/esp connections.                      */
  141.  /****************************************************************************/
  142.  if( (SerialParallel() == SERIAL) )
  143.   LsnHandle = GetComHandle();
  144.  
  145.  QueHandle = (LHANDLE)qHandle;
  146.  EleCode   = 0;
  147.  
  148.  /****************************************************************************/
  149.  /* - The starting of the queue is delayed until this flag is set.  The      */
  150.  /*   reason is that in some cases, the DosStartSession() may cause the      */
  151.  /*   queue to be posted before(!)  the queue thread gets started.  So,      */
  152.  /*   we want to guarantee that que will be started and ready to read        */
  153.  /*   before DosStartSession() is executed.                                  */
  154.  /****************************************************************************/
  155.  ReadQueReady = TRUE;
  156.  
  157.  for(; EndThread == FALSE ;)
  158.  {
  159.   /***************************************************************************/
  160.   /* We're going to read an element from the esp queue.  The queue is read   */
  161.   /* in FIFO order and we wait until there is a message to read.  We get an  */
  162.   /* element priority but we don't care about it.  Request.ulData contains   */
  163.   /* the message.                                                            */
  164.   /*                                                                         */
  165.   /***************************************************************************/
  166.   rc = DosReadQueue(QueHandle,
  167.                     &Request,
  168.                     &DataLen,
  169.                     (PPVOID)&pDataAddr,
  170.                     EleCode,
  171.                     DCWW_WAIT,
  172.                     &ElePri,
  173.                     0L);
  174.  
  175.   /***************************************************************************/
  176.   /* - Handle the private verbose option.                                    */
  177.   /***************************************************************************/
  178.   if( IsVerbose() ) PrintQueMessage( &Request,pDataAddr);
  179.  
  180.   switch( Request.ulData )
  181.   {
  182.    case ESP_QMSG_SELECT_SESSION:
  183.     pid = pDataAddr->ChildPid;
  184.     p   = GetPid( pid );
  185.     rc  = DosSelectSession( p->sid );
  186.     if( IsVerbose() ) {printf("\nSelect Session id=%d rc=%d",p->sid, rc);fflush(0);}
  187.     break;
  188.  
  189.    case ESP_QMSG_END_SESSION:
  190.     break;
  191.  
  192.    case ESP_QMSG_OPEN_CONNECT:
  193.     /*************************************************************************/
  194.     /* - This message comes with parallel connections only.                  */
  195.     /* - A separate connection is established between the dbg and esp ques.  */
  196.     /*************************************************************************/
  197.     OpenAnotherConnection( &LsnHandle );
  198.     _beginthread(ListenForMsgFromDbg,NULL,0x8000,(void *)LsnHandle);
  199.     break;
  200.  
  201.    case ESP_QMSG_NEW_SESSION:
  202.    case ESP_QMSG_NEW_PROCESS:
  203.     /*************************************************************************/
  204.     /*                                                                       */
  205.     /* - DosStartSession() will send the queue a new session notification    */
  206.     /*   when the parent process is started. We ignore that notification     */
  207.     /*   and send our own new process notification from EspStartUser().      */
  208.     /* - The parent probe will debug the parent process or the first         */
  209.     /*   child process that has been designated as debuggable.               */
  210.     /* - After the parent probe locks in on the process that it will         */
  211.     /*   be debugging, subsequent child processes will be assigned a         */
  212.     /*   child probe.                                                        */
  213.     /* - If a new process notification comes for a non-debug process,        */
  214.     /*   then we simply start a generic spin thread to handle it.            */
  215.     /*                                                                       */
  216.     /*           Is this pid one that we're debugging?                       */
  217.     /*             |                              |                          */
  218.     /*             | TRUE                         | FALSE                    */
  219.     /*             |                              |                          */
  220.     /*     Has the Parent Session           Start a spin thread.             */
  221.     /*     been started?                                                     */
  222.     /*      |                  |                                             */
  223.     /*      | TRUE             | FALSE                                       */
  224.     /*      |                  |                                             */
  225.     /*     Spawn a probe      Release the parent                             */
  226.     /*     for this process.  session and note                               */
  227.     /*                        parent started.                                */
  228.     /*                                                                       */
  229.     /*************************************************************************/
  230.     pid = pDataAddr->ChildPid;
  231.  
  232.     if( IsProcessInList(pid) == TRUE)
  233.      continue;
  234.  
  235.     AddProcessToList(pid);
  236.  
  237.     TorF = IsDebug( NULL, pid, &sid, &type, &mte );
  238.     if( IsVerbose() )
  239.     {
  240.      CHAR ModNameBuf[CCHMAXPATH];
  241.  
  242.      DosQueryModuleName( mte, CCHMAXPATH, ModNameBuf );
  243.      printf("\n%s", ModNameBuf);
  244.      printf(" pid=%d sid=%d", pid, sid);
  245.      fflush(0);
  246.     }
  247.     /*************************************************************************/
  248.     /* - Add the pid to the list of pids and set a bit to indicate           */
  249.     /*   whether or not this pid is being debugged.                          */
  250.     /*************************************************************************/
  251.  
  252.     AddPid(pid, 0, 0, 0, NULL );
  253.     p = GetPid( pid );
  254.     p->PidFlags.IsDebug = TorF;
  255.  
  256.     /*************************************************************************/
  257.     /* - if we're debugging a single child process and that process is       */
  258.     /*   being exec'd multiple times, then we debug only the first instance. */
  259.     /*************************************************************************/
  260.     if( (TorF == TRUE) &&
  261.         (SingleMultiple() == SINGLE) &&
  262.         (ParentStarted == TRUE)
  263.       )
  264.     {
  265.      _beginthread( SpinThread, NULL, 0x8000, (void*)pid);
  266.      continue;
  267.     }
  268.  
  269.     if( TorF == FALSE )
  270.     {
  271.      /************************************************************************/
  272.      /* - Not debugging this process...start a thread to run it.             */
  273.      /************************************************************************/
  274.      _beginthread( SpinThread, NULL, 0x8000, (void*)pid);
  275.     }
  276.     else
  277.     {
  278.      if( ParentStarted == TRUE )
  279.      {
  280.       /***********************************************************************/
  281.       /* - This process is one that we want to debug.                        */
  282.       /* - Come here if the parent probe has already been started.           */
  283.       /***********************************************************************/
  284.       USHORT            EspPid;
  285.       ULONG             EspSid;
  286.       ULONG             ErrorMsgLen;
  287.       QUE_ERR_ELEMENT   Que_ErrElement;
  288.  
  289.       /***********************************************************************/
  290.       /* - Send a message to the dbg que about the new process.              */
  291.       /***********************************************************************/
  292.       if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  293.       {
  294.        SQE_NEW_PROCESS sqe;
  295.        sqe.pid  = pid;
  296.        sqe.type = type;
  297.        sqe.mte  = mte;
  298.        AddMessage( NEW_PROCESS, &sqe, sizeof(sqe) );
  299.       }
  300.       else
  301.       {
  302.        SendNewProcessToDbg( LsnHandle, pid, type, mte );
  303.       }
  304.       /***********************************************************************/
  305.       /* - Start the probe and handle any errors.                            */
  306.       /***********************************************************************/
  307.       {
  308.        ESP_SPAWN_FLAGS SpawnFlags;
  309.  
  310.        /**********************************************************************/
  311.        /* - Define the flags telling SpawnProbe() how to spawn the child     */
  312.        /*   child probe.                                                     */
  313.        /* - When running child/multiple processes on a single machine,       */
  314.        /*   the probes are made invisible. They will still show up in the    */
  315.        /*   task list.                                                       */
  316.        /**********************************************************************/
  317.        SpawnFlags.Visible     = ESP_VISIBLE;
  318.        SpawnFlags.SpawnMethod = ESP_USE_DOSSTARTSESSION;
  319.  
  320.        if( UseExecPgm() == TRUE )
  321.         SpawnFlags.SpawnMethod = ESP_USE_DOSEXECPGM;
  322.        else
  323.         if( ConnectType()==LOCAL_PIPE )
  324.          SpawnFlags.Visible = ESP_INVISIBLE;
  325.  
  326.        ErrorMsgLen = sizeof(Que_ErrElement.ErrorMsg);
  327.  
  328.        memset( Que_ErrElement.ErrorMsg, 0, ErrorMsgLen );
  329.  
  330.        SpawnFlags.SpawnOrigin = ESP_SPAWN_FROM_ESP;
  331.        rc = SpawnProbe( &EspPid,
  332.                         &EspSid,
  333.                          EspQueName,
  334.                          ErrorMsgLen-1, /* guarantee null termination. */
  335.                          Que_ErrElement.ErrorMsg,
  336.                          SpawnFlags );
  337.       }
  338.       if( rc )
  339.       {
  340.        Que_ErrElement.rc = rc;
  341.  
  342.        SendMsgToEspQue(ESP_QMSG_ERROR, &Que_ErrElement, sizeof(Que_ErrElement));
  343.       }
  344.  
  345.       /***********************************************************************/
  346.       /* - Add the session id and process id of the "probe" to the           */
  347.       /*   structure for this pid.                                           */
  348.       /* - When there is a flurry of new process notifications we cannot     */
  349.       /*   guarantee that the probe generated for this pid will be connected */
  350.       /*   to by the debugger for this pid.  So,we invalidate the pid making */
  351.       /*   the probe we've just spawned a generic probe.  Later, a debugger  */
  352.       /*   will connect to this probe and tell it what pid it will be        */
  353.       /*   debugging.                                                        */
  354.       /* - However, we need to make a note that there has been a probe       */
  355.       /*   spawned for the new process pid so that we don't spawn multiple   */
  356.       /*   probes for a pid.                                                 */
  357.       /***********************************************************************/
  358.       p                   = GetPid( pid );
  359.       p->EspPid           = EspPid;
  360.       p->EspSid           = EspSid;
  361.       p->pid              = 0;
  362.  
  363.       /***********************************************************************/
  364.       /* - Wait for the connect sema4 to be created and put into the shared  */
  365.       /*   heap structure.                                                   */
  366.       /***********************************************************************/
  367.       if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  368.       {
  369.        while( p->ConnectSema4 == 0 ) { DosSleep(200); }
  370.       }
  371.      }
  372.      else
  373.      {
  374.       /***********************************************************************/
  375.       /* - Come here if the parent probe has not been started.               */
  376.       /***********************************************************************/
  377.       ParentStarted = TRUE;
  378.       SetParentProcessID( pid);
  379.       SetParentSessionID( sid);
  380.       PostWait4ChildSema4();
  381.      }
  382.     }
  383.     break;
  384.  
  385.    case ESP_QMSG_CTRL_BREAK:
  386.     /*************************************************************************/
  387.     /* - This message comes when the user enters Ctrl-Break and responds     */
  388.     /*   that he wants to "stop the debuggee."                               */
  389.     /*************************************************************************/
  390.     {
  391.      USHORT             YieldPid;
  392.      USHORT             CtrlBreakPid;
  393.      ALLPIDS           *pYield;
  394.      ALLPIDS           *pCtrlBreak;
  395.      SQE_MESSAGE       *pSqe;
  396.  
  397.      CtrlBreakPid = pDataAddr->ChildPid;
  398.      pCtrlBreak   = GetPid( CtrlBreakPid );
  399.  
  400.      if( (SerialParallel() == SERIAL) && (SingleMultiple() == MULTIPLE) )
  401.      {
  402.       /***********************************************************************/
  403.       /* - If the connection is serial, then we have to:                     */
  404.       /*    - Disconnect a pid that may be currently connected.              */
  405.       /*    - Connect the pid that's the target of the ctrl-break.           */
  406.       /*    - Send the kill process signal unless there is a connect request */
  407.       /*      queued for the target pid. In this case, simply let the        */
  408.       /*      connect be processed.                                          */
  409.       /***********************************************************************/
  410.       pCtrlBreak->Connect = CONNECTED;
  411.  
  412.       YieldPid         = pDataAddr->ChildSid;
  413.       pYield           = GetPid( YieldPid );
  414.       if(pYield)
  415.        pYield->Connect = DISCONNECTED;
  416.  
  417.       pSqe = IsConnectRequestQueued( pid );
  418.       if( pSqe )
  419.        RemoveMessage( pSqe );
  420.       else
  421.       {
  422.        pCtrlBreak->PidFlags.CtrlBreak = TRUE;
  423.        DosKillProcess( DKP_PROCESS, pCtrlBreak->EspPid );
  424.       }
  425.       TorF = TRUE;
  426.       if( CtrlBreakPid == GetEspProcessID() )
  427.        TorF = FALSE;
  428.  
  429.       PostConnectSema4( &pCtrlBreak->ConnectSema4, TorF );
  430.      }
  431.      else
  432.      {
  433.       /***********************************************************************/
  434.       /* - If connected with a parallel connection, then send the kill       */
  435.       /*   process signal.                                                   */
  436.       /***********************************************************************/
  437.       pCtrlBreak->PidFlags.CtrlBreak = TRUE;
  438.       DosKillProcess( DKP_PROCESS, (PID)(pCtrlBreak->EspPid) );
  439.      }
  440.     }
  441.     break;
  442.  
  443. /*---------------------------------------------------------------------------*/
  444. /* All of the messages until the next dashed comment line are for serial     */
  445. /* connections only.                                                         */
  446. /*---------------------------------------------------------------------------*/
  447.  
  448.    case ESP_QMSG_CONNECT_REQUEST:
  449.     /*************************************************************************/
  450.     /* - Serial connect message only.                                        */
  451.     /* - One of the esp services has a notification to report.               */
  452.     /* - If we're debugging a single process, then simply post the sema4.    */
  453.     /* - If we're debugging multiple processes, then add the message to the  */
  454.     /*   message queue in the shared heap. It will be polled in by the       */
  455.     /*   dbg.                                                                */
  456.     /*************************************************************************/
  457.     p = GetPid( pDataAddr->ChildPid );
  458.     pid = p->pid;
  459.     if( SingleMultiple() == MULTIPLE )
  460.      AddMessage( CONNECT_DBG, &pid, sizeof(pid) );
  461.     else
  462.     {
  463.      p->Connect = CONNECTED;
  464.  
  465.      SetPeekForCtrlBreakFlag( FALSE );
  466.      PostConnectSema4( &p->ConnectSema4, FALSE );
  467.     }
  468.     break;
  469.  
  470.    case ESP_QMSG_DISCONNECT:
  471.     /*************************************************************************/
  472.     /* - Serial connect message only.                                        */
  473.     /* - One of the esp execution services is being executed and is          */
  474.     /*   giving up its connection.                                           */
  475.     /* - If debugging multiple processes, then start a thread to respond     */
  476.     /*   to the polling requests from the dbg.                               */
  477.     /*************************************************************************/
  478.     p          = GetPid( pDataAddr->ChildPid );
  479.     p->Connect = DISCONNECTED;
  480.     if( SingleMultiple() == MULTIPLE )
  481.      _beginthread( WaitForConnection, NULL, 0x8000, NULL );
  482.     else
  483.      _beginthread( PeekForCtrlBreak, NULL, 0x8000, NULL );
  484.     break;
  485.  
  486. /*---------------------------------------------------------------------------*/
  487.  
  488.    case ESP_QMSG_SELECT_ESP:
  489.     /*************************************************************************/
  490.     /* - Bring the probe for this pid to the foreground. Used to display     */
  491.     /*   error messages.                                                     */
  492.     /*************************************************************************/
  493.     pid = pDataAddr->ChildPid;
  494.     p   = GetEspPid( pid );
  495.     DosSelectSession( p->EspSid );
  496.     break;
  497.  
  498.    case ESP_QMSG_PARENT_TERM:
  499.  
  500.     /*************************************************************************/
  501.     /* - Set a flag so that child termination messages will not start        */
  502.     /*   connection threads when running serial.                             */
  503.     /*************************************************************************/
  504.     ParentTerminating = TRUE;
  505.     /*************************************************************************/
  506.     /* - The parent probe is terminating.                                    */
  507.     /* - Note: At this point the AllProbesAreDeadFlag==FALSE.                */
  508.     /*************************************************************************/
  509.     for( p = GetAllpids(); p ; p = p->next )
  510.     {
  511.      if( (p->PidFlags.IsDebug) == TRUE && (p->pid != GetEspProcessID()) )
  512.      {
  513.       ESP_QUE_ELEMENT Qelement;
  514.  
  515.       Qelement.ChildPid = p->EspPid;
  516.  
  517.       SendMsgToEspTermQue(ESP_TERMINATE, &Qelement, sizeof(Qelement) );
  518.      }
  519.     }
  520.  
  521.     /*************************************************************************/
  522.     /* - now, remove the pid structures from the list for the processes      */
  523.     /*   that are NOT being debugged.                                        */
  524.     /*************************************************************************/
  525.     for( p = GetAllpids(); p ; p = p->next )
  526.     {
  527.      if( (p->PidFlags.IsDebug) == FALSE && (p->pid != GetEspProcessID()) )
  528.      {
  529.       RemovePid( p->pid );
  530.      }
  531.     }
  532.  
  533.     /*************************************************************************/
  534.     /* - There may not be any child probes, so set this flag so the parent   */
  535.     /*   can terminate.                                                      */
  536.     /*************************************************************************/
  537.     if(GetAllpids()->next == NULL)
  538.     {
  539.      AllProbesAreDeadFlag = TRUE;
  540.     }
  541.     break;
  542.  
  543.    case ESP_QMSG_CHILD_TERM:
  544.     /*************************************************************************/
  545.     /* - A child probe has terminated.                                       */
  546.     /*************************************************************************/
  547.     RemovePid( pDataAddr->ChildPid );
  548.  
  549.     /*************************************************************************/
  550.     /* - After the last probe has terminated, then report all probes dead.   */
  551.     /*************************************************************************/
  552.     if(GetAllpids()->next == NULL)
  553.     {
  554.      AllProbesAreDeadFlag = TRUE;
  555.     }
  556.     if( (ParentTerminating == FALSE)    &&
  557.         (SerialParallel()  == SERIAL)   &&
  558.         (SingleMultiple()  == MULTIPLE)
  559.       )
  560.      _beginthread( WaitForConnection, NULL, 0x8000, NULL );
  561.     break;
  562.  
  563.    case ESP_QMSG_QUE_TERM:
  564.     /*************************************************************************/
  565.     /* - Terminate and reset the queue for a possible restart.               */
  566.     /* - Free memory allocated for the pid structures.                       */
  567.     /*************************************************************************/
  568.     DosCloseQueue(QueHandle);
  569.  
  570.     if( (SerialParallel() == PARALLEL) && LsnHandle )
  571.      ConnectClose( LsnHandle );
  572.  
  573.     if( SingleMultiple() == MULTIPLE )
  574.      FreeSharedHeap();
  575.  
  576.     ParentStarted = FALSE;
  577.     EndThread     = TRUE;
  578.     ReadQueReady  = 0;
  579.     break;
  580.  
  581.    case ESP_QMSG_ERROR:
  582.     {
  583.      QUE_ERR_ELEMENT *pQueErrElement =  (QUE_ERR_ELEMENT *)pDataAddr;
  584.      char            *pErrorMsg;
  585.      char             RcMessage[32];
  586.  
  587.      rc        = pQueErrElement->rc;
  588.      pErrorMsg = pQueErrElement->ErrorMsg;
  589.  
  590.      DosSelectSession(0);
  591.  
  592.      sprintf( RcMessage, "Esp Error rc=%d", rc );
  593.  
  594.      ErrorPrintf( ERR_ESP_QUE_ERROR, 2, RcMessage, pErrorMsg );
  595.     }
  596.     break;
  597.  
  598.    default:
  599.     break;
  600.  
  601.   }
  602.  
  603.   /***************************************************************************/
  604.   /* - Free the shared memory used for the message and initialize the        */
  605.   /*   data element pointer for the next message.                            */
  606.   /***************************************************************************/
  607.   if(pDataAddr) DosFreeMem(pDataAddr);
  608.   pDataAddr = NULL;
  609.  }
  610.  if( IsVerbose() ) {printf("\nEsp Que Ended");fflush(0);}
  611.  _endthread();
  612. }                                       /* end ReadQ().                      */
  613.  
  614. /*****************************************************************************/
  615. /* SendMsgToEspQue()                                                         */
  616. /*                                                                           */
  617. /* Description:                                                              */
  618. /*                                                                           */
  619. /*  Send ESP_QMSG_xxxxxx message to ESP queue.                               */
  620. /*                                                                           */
  621. /* Parameters:                                                               */
  622. /*                                                                           */
  623. /*   Msg            ESP_QMSG_xxxxxx message.                                 */
  624. /*   PQueElement    -> to optional queue element.                            */
  625. /*   QueElementLen  length of the queue element.                             */
  626. /*                                                                           */
  627. /* Return:                                                                   */
  628. /*                                                                           */
  629. /* Assumptions:                                                              */
  630. /*                                                                           */
  631. /*****************************************************************************/
  632. void SendMsgToEspQue( ULONG Msg , void *pQueElement, ULONG QueElementLen)
  633. {
  634.  SendMsgToQue( EspQueName, Msg, pQueElement, QueElementLen );
  635. }
  636.  
  637. /*****************************************************************************/
  638. /* ListenForMsgFromDbg()                                                     */
  639. /*                                                                           */
  640. /* Description:                                                              */
  641. /*                                                                           */
  642. /*   This function runs in its own thread and listens messages coming        */
  643. /*   to the queue from esp. This thread only exists when we're running       */
  644. /*   with a parallel connection.                                             */
  645. /*                                                                           */
  646. /* Parameters:                                                               */
  647. /*                                                                           */
  648. /*   handle   connection handle.                                             */
  649. /*                                                                           */
  650. /* Return:                                                                   */
  651. /*                                                                           */
  652. /* Assumptions:                                                              */
  653. /*                                                                           */
  654. /*****************************************************************************/
  655. void ListenForMsgFromDbg( void *handle )
  656. {
  657.  LHANDLE LsnHandle = (LHANDLE)handle;
  658.  COMMAND cmd;
  659.  BOOL    EndThread;
  660.  
  661.  if( IsVerbose() ) {printf("\nListen thread started");fflush(0);}
  662.  for( EndThread = FALSE ; EndThread == FALSE ; )
  663.  {
  664.   RmtRecv( LsnHandle,&cmd,sizeof(cmd) );
  665.   if( IsVerbose() ) PrintCmdMessage( cmd.api ) ;
  666.   switch( cmd.api )
  667.   {
  668.    case CTRL_BREAK:
  669.    {
  670.     ESP_QUE_ELEMENT Qelement;
  671.     USHORT          CtrlBreakPid;
  672.  
  673.     RmtRecv( LsnHandle, &CtrlBreakPid, cmd.len );
  674.  
  675.     Qelement.ChildPid = CtrlBreakPid;
  676.     Qelement.ChildSid = 0;
  677.  
  678.     SendMsgToEspQue(ESP_QMSG_CTRL_BREAK, &Qelement, sizeof(Qelement));
  679.    }
  680.    break;
  681.  
  682.    case KILL_LISTEN_THREAD:
  683.    /**************************************************************************/
  684.    /* - This command will come from the dbg queue when it gets a command     */
  685.    /*   to kill the listen thread during termination. The reason we do       */
  686.    /*   it this way is that DosKillThread() was causing a session hang       */
  687.    /*   when using MPTS on LS 4.0, so now, the debugger sends a command      */
  688.    /*   to the probe telling it to kill its listen thread. The probe sends   */
  689.    /*   a command back to the debugger telling it to also kill its listen    */
  690.    /*   thread.                                                              */
  691.    /**************************************************************************/
  692.    {
  693.     cmd.api  = KILL_LISTEN_THREAD;
  694.     cmd.cmd  = 0;
  695.     cmd.len  = 0;
  696.  
  697.     RmtSend( LsnHandle, &cmd , sizeof(cmd) );
  698.     EndThread = TRUE;
  699.    }
  700.    break;
  701.   }
  702.  }
  703.  if( IsVerbose() ) {printf("\nListen thread ended");fflush(0);}
  704.  _endthread();
  705. }
  706.  
  707. /*****************************************************************************/
  708. /* WaitForConnection()                                                       */
  709. /*                                                                           */
  710. /* Description:                                                              */
  711. /*                                                                           */
  712. /*   This thread spins when there is no probe to debugger connection         */
  713. /*   which happens after the queue processes an ESP_QMSG_DISCONNECT.  The    */
  714. /*   dbg will be polling for the next probe to connect and this thread       */
  715. /*   will make the connection and will die after the connect is made.        */
  716. /*                                                                           */
  717. /* Parameters:                                                               */
  718. /*                                                                           */
  719. /* Return:                                                                   */
  720. /*                                                                           */
  721. /* Assumptions:                                                              */
  722. /*                                                                           */
  723. /*****************************************************************************/
  724. void WaitForConnection( void *dummy )
  725. {
  726.  LHANDLE LsnHandle;
  727.  COMMAND cmd;
  728.  BOOL    EndThread=FALSE;
  729.  
  730.  
  731.  if( IsVerbose() ) {printf("\nWait for connection started");fflush(0);}
  732.  LsnHandle = GetComHandle();
  733.  for(; EndThread==FALSE ; )
  734.  {
  735.   RmtRecv( LsnHandle,&cmd,sizeof(cmd) );
  736.   if( IsVerbose() ) PrintCmdMessage( cmd.api ) ;
  737.   switch( cmd.api )
  738.   {
  739.    case SERIAL_POLL:
  740.     ReportMessage();
  741.     break;
  742.  
  743.    case CONNECT_ESP:
  744.    {
  745.     USHORT   GoToPid;
  746.     ALLPIDS *pGoTo;
  747.     BOOL     TorF;
  748.  
  749.     /*************************************************************************/
  750.     /* - Receive the pid to be connected and mark it connected.              */
  751.     /* - If this pid has not yet been assigned to a probe, then pGoTo        */
  752.     /*   will be NULL.                                                       */
  753.     /* - There MUST be a probe with a pid==0, so we release that probe.      */
  754.     /*   ( The pid will be stuffed into the structure at goinit() time.)     */
  755.     /* - Post the connect sema4 for the goto pid.                            */
  756.     /*************************************************************************/
  757.     RmtRecv( LsnHandle, &GoToPid, cmd.len );
  758.     pGoTo          = GetPid( GoToPid );
  759.  
  760.     if( pGoTo == NULL )
  761.      pGoTo = GetPid(0);
  762.  
  763.     pGoTo->Connect = CONNECTED;
  764.  
  765.     TorF = TRUE;
  766.     if( GoToPid == GetEspProcessID() )
  767.      TorF = FALSE;
  768.  
  769.     /*************************************************************************/
  770.     /* - Send back verification that the connection has been made.           */
  771.     /*************************************************************************/
  772.     memset(&cmd,0,sizeof(cmd) );
  773.  
  774.     cmd.api = CONNECT_ESP;
  775.     RmtSend( LsnHandle, &cmd, sizeof(cmd) );
  776.  
  777.     /*************************************************************************/
  778.     /* - A little insurance to make sure the sema4 has been created.         */
  779.     /*************************************************************************/
  780.     while( pGoTo->ConnectSema4 == 0 ) { DosSleep(200); }
  781.     PostConnectSema4( &pGoTo->ConnectSema4, TorF );
  782.     EndThread = TRUE;
  783.    }
  784.    break;
  785.  
  786.    case CTRL_BREAK:
  787.    {
  788.     ESP_QUE_ELEMENT Qelement;
  789.     USHORT          CtrlBreakPid;
  790.  
  791.     RmtRecv( LsnHandle, &CtrlBreakPid, cmd.len );
  792.  
  793.     Qelement.ChildPid = CtrlBreakPid;
  794.     Qelement.ChildSid = 0;
  795.  
  796.     SendMsgToEspQue(ESP_QMSG_CTRL_BREAK, &Qelement, sizeof(Qelement));
  797.     EndThread=TRUE;
  798.  
  799.    }
  800.    break;
  801.  
  802.   }
  803.   if( IsPidConnected() )
  804.   {
  805.     EndThread=TRUE;
  806.   }
  807.  }
  808.  if( IsVerbose() ) {printf("\nWait for connection ended");fflush(0);}
  809.  _endthread();
  810. }
  811.  
  812.  
  813. /*****************************************************************************/
  814. /* SendNewProcessToDbg()                                                     */
  815. /*                                                                           */
  816. /* Description:                                                              */
  817. /*                                                                           */
  818. /*  Send a new process notification back to the dbg.                         */
  819. /*                                                                           */
  820. /* Parameters:                                                               */
  821. /*                                                                           */
  822. /*   handle      handle of the connection.                                   */
  823. /*   pid         process id of the new process.                              */
  824. /*   type        type of the new process.                                    */
  825. /*   mte         module handle of the new process.                           */
  826. /*                                                                           */
  827. /* Return:                                                                   */
  828. /*                                                                           */
  829. /* Assumptions:                                                              */
  830. /*                                                                           */
  831. /*****************************************************************************/
  832. void SendNewProcessToDbg( LHANDLE handle,
  833.                           USHORT  pid,
  834.                           ULONG   type,
  835.                           USHORT  mte )
  836. {
  837.  COMMAND cmd;
  838.  int     size;
  839.  
  840.  TXRX_NEW_PROCESS packet;
  841.  
  842.  cmd.api = NEW_PROCESS;
  843.  cmd.cmd = NEW_PROCESS;
  844.  cmd.len = sizeof(packet) - sizeof(packet.ProcessFileSpec);
  845.  
  846.  size = sizeof(packet.ProcessFileSpec);
  847.  memset(packet.ProcessFileSpec, 0, size );
  848.  DosQueryModuleName( mte, size, packet.ProcessFileSpec );
  849.  
  850.  packet.pid  = pid;
  851.  packet.type = type;
  852.  
  853.  cmd.len += strlen(packet.ProcessFileSpec) + 1;
  854.  
  855.  RmtSend( handle, &cmd, sizeof(cmd) );
  856.  RmtSend( handle, &packet, cmd.len );
  857.  
  858. }
  859.  
  860. /*****************************************************************************/
  861. /* ConnectDbg()                                                              */
  862. /*                                                                           */
  863. /* Description:                                                              */
  864. /*                                                                           */
  865. /*  Send a connect command to the dbg que.                                   */
  866. /*                                                                           */
  867. /* Parameters:                                                               */
  868. /*                                                                           */
  869. /*   handle      handle of the connection.                                   */
  870. /*   pid         process id of the new process.                              */
  871. /*                                                                           */
  872. /* Return:                                                                   */
  873. /*                                                                           */
  874. /* Assumptions:                                                              */
  875. /*                                                                           */
  876. /*   This function is only called for serial connections.                    */
  877. /*                                                                           */
  878. /*****************************************************************************/
  879. void ConnectDbg( LHANDLE handle, USHORT pid )
  880. {
  881.  COMMAND cmd;
  882.  
  883.  /****************************************************************************/
  884.  /* - The probe does not send messages to the dbg when debugging a single    */
  885.  /*   parent or child process.                                               */
  886.  /****************************************************************************/
  887.  if( SingleMultiple() == SINGLE )
  888.   return;
  889.  
  890.  cmd.api = CONNECT_DBG;
  891.  cmd.cmd = CONNECT_DBG;
  892.  cmd.len = sizeof(pid);
  893.  
  894.  RmtSend( handle, &cmd, sizeof(cmd) );
  895.  RmtSend( handle, &pid, cmd.len );
  896.  RmtRecv( handle, &cmd, sizeof(cmd) );
  897. }
  898.  
  899. /*****************************************************************************/
  900. /* PeekForCtrlBreak()                                                        */
  901. /*                                                                           */
  902. /* Description:                                                              */
  903. /*                                                                           */
  904. /*  When debugging a single process whether parent or child and we're        */
  905. /*  using a serial connection, then we need to peek the connection to see    */
  906. /*  if there has been a ctrl-break sent from the dbg.                        */
  907. /*                                                                           */
  908. /* Parameters:                                                               */
  909. /*                                                                           */
  910. /* Return:                                                                   */
  911. /*                                                                           */
  912. /* Assumptions:                                                              */
  913. /*                                                                           */
  914. /*   The only function that can come across the serial connection is         */
  915. /*   ctrl-break so when there is something to peek it is "assumed"           */
  916. /*   that it's a ctrl-break.                                                 */
  917. /*                                                                           */
  918. /*****************************************************************************/
  919. static BOOL PeekForCtrlBreakFlag = TRUE;
  920. void   SetPeekForCtrlBreakFlag( BOOL TorF ) { PeekForCtrlBreakFlag = TorF;}
  921. BOOL   GetPeekForCtrlBreakFlag( void ) { return( PeekForCtrlBreakFlag ); }
  922.  
  923. void PeekForCtrlBreak( void* dummy )
  924. {
  925.  
  926.  if( IsVerbose() ) {printf("\nPeek ctrl-break started");fflush(0);}
  927.  for(; PeekForCtrlBreakFlag==TRUE;)
  928.  {
  929.   if( AsyncPeekComPort() )
  930.   {
  931.    COMMAND cmd = {0,0};
  932.  
  933.    memset(&cmd,0,sizeof(cmd) );
  934.    RmtRecv(DEFAULT_HANDLE, (char*)&cmd, sizeof(cmd));
  935.    if( IsVerbose() ) PrintCmdMessage( cmd.api ) ;
  936.    switch( cmd.api )
  937.    {
  938.     case CTRL_BREAK:
  939.     {
  940.      ESP_QUE_ELEMENT Qelement;
  941.      USHORT          CtrlBreakPid;
  942.  
  943.      RmtRecv( DEFAULT_HANDLE, &CtrlBreakPid, cmd.len );
  944.  
  945.      Qelement.ChildPid = CtrlBreakPid;
  946.      Qelement.ChildSid = 0;
  947.  
  948.      SendMsgToEspQue(ESP_QMSG_CTRL_BREAK, &Qelement, sizeof(Qelement));
  949.      PeekForCtrlBreakFlag=FALSE;
  950.     }
  951.     break;
  952.  
  953.     default:
  954.     break;
  955.    }
  956.   }
  957.   DosSleep(300);
  958.  }
  959.  PeekForCtrlBreakFlag=TRUE;
  960.  if( IsVerbose() ) {printf("\nPeek ctrl-break ended");fflush(0);}
  961.  _endthread();
  962. }
  963.  
  964. /*****************************************************************************/
  965. /* StartEspTermQue()                                                         */
  966. /*                                                                           */
  967. /* Description:                                                              */
  968. /*                                                                           */
  969. /*  Start up a que for terminating the debugger.                             */
  970. /*                                                                           */
  971. /* Parameters:                                                               */
  972. /*                                                                           */
  973. /* Return:                                                                   */
  974. /*                                                                           */
  975. /*  rc    System API return code.                                            */
  976. /*                                                                           */
  977. /* Assumptions:                                                              */
  978. /*                                                                           */
  979. /*****************************************************************************/
  980. static PSZ TermQueBaseName = "\\QUEUES\\TermQue";
  981.  
  982. APIRET StartEspTermQue( void )
  983. {
  984.  APIRET   rc;
  985.  TIB     *pTib;
  986.  PIB     *pPib;
  987.  USHORT   ThisPid;
  988.  char     TermQueName[32];
  989.  char     PidString[12];
  990.  ALLPIDS *p;
  991.  
  992.  /****************************************************************************/
  993.  /* - Get the pid of this debugger and use it to define a unique name        */
  994.  /*   for this debugger's termination que.                                   */
  995.  /* - Stuff in the base que name.                                            */
  996.  /* - Concatenate the pid to make the name unique for the system.            */
  997.  /****************************************************************************/
  998.  DosGetInfoBlocks(&pTib, &pPib);
  999.  ThisPid = (USHORT)pPib->pib_ulpid;
  1000.  
  1001.  memset(TermQueName, 0, sizeof(TermQueName));
  1002.  strcat(TermQueName, TermQueBaseName);
  1003.  
  1004.  memset(PidString, 0, sizeof(PidString));
  1005.  sprintf( PidString, "%d", ThisPid );
  1006.  strcat(TermQueName, PidString );
  1007.  
  1008.  /****************************************************************************/
  1009.  /* - Now, start the que with a thread for this debugger.                    */
  1010.  /****************************************************************************/
  1011.  rc = StartQue(TermQueName, ReadEspTermQue );
  1012.  if(rc) return(rc);
  1013.  
  1014.  /****************************************************************************/
  1015.  /* - Now, add the name of the queue to the shared memory structure for      */
  1016.  /*   this debugger.                                                         */
  1017.  /****************************************************************************/
  1018.  p = GetEspPid( ThisPid );
  1019.  
  1020.  DosSubAllocMem( GetShrMem(), (PPVOID)&(p->pTermQue), strlen(TermQueName) + 1 );
  1021.  strcpy(p->pTermQue, TermQueName );
  1022.  
  1023.  return(0);
  1024. }
  1025.  
  1026. /*****************************************************************************/
  1027. /* ReadEspTermQue()                                                          */
  1028. /*                                                                           */
  1029. /* Description:                                                              */
  1030. /*                                                                           */
  1031. /*   Read and handle termination message(s) coming to this probe             */
  1032. /*   from the parent probe.                                                  */
  1033. /*                                                                           */
  1034. /* Parameters:                                                               */
  1035. /*                                                                           */
  1036. /*   qHandle        -> to the queue handle. This is passed in by the         */
  1037. /*                     StartQue() function when the queue is created.        */
  1038. /*                                                                           */
  1039. /* Return:                                                                   */
  1040. /*                                                                           */
  1041. /*  void                                                                     */
  1042. /*                                                                           */
  1043. /* Assumptions:                                                              */
  1044. /*                                                                           */
  1045. /*  This function runs in its own thread.                                    */
  1046. /*                                                                           */
  1047. /*****************************************************************************/
  1048. void ReadEspTermQue( void *qHandle)
  1049. {
  1050.  REQUESTDATA  Request;
  1051.  ULONG        DataLen;
  1052.  BYTE         ElePri;
  1053.  BOOL         EndThread = FALSE;
  1054.  LHANDLE      TermQueHandle;
  1055.  
  1056.  ESP_QUE_ELEMENT *pDataAddr=NULL;
  1057.  
  1058.  TermQueHandle    = (LHANDLE)qHandle;
  1059.  
  1060.  /****************************************************************************/
  1061.  /* - Start the que reading loop.                                            */
  1062.  /****************************************************************************/
  1063.  for(; EndThread == FALSE ;)
  1064.  {
  1065.   /***************************************************************************/
  1066.   /* We're going to read an element from the term queue.  The queue is read  */
  1067.   /* in FIFO order and we wait until there is a message to read.  We get an  */
  1068.   /* element priority but we don't care about it.  Request.ulData contains   */
  1069.   /* the message.                                                            */
  1070.   /***************************************************************************/
  1071.   DosReadQueue(TermQueHandle,
  1072.                &Request,
  1073.                &DataLen,
  1074.                (PPVOID)&pDataAddr,
  1075.                QUE_FIFO,
  1076.                DCWW_WAIT,
  1077.                &ElePri,
  1078.                0L);
  1079.  
  1080.   /***************************************************************************/
  1081.   /* - Handle the termination que message(s).                                */
  1082.   /***************************************************************************/
  1083.   switch( Request.ulData )
  1084.   {
  1085.    case ESP_TERMINATE:
  1086.    {
  1087.     ALLPIDS *p;
  1088.     ULONG    EntryPt = 0;
  1089.     USHORT   pid;
  1090.     USHORT   mte;
  1091.  
  1092.     ESP_QUE_ELEMENT Qelement;
  1093.  
  1094.     /*************************************************************************/
  1095.     /* - At this point, thread 1 could be blocked in DosDebug(). When        */
  1096.     /*   we make the normalquit() call, then thread 1 may return and         */
  1097.     /*   try return back to the debugger resulting in a communications       */
  1098.     /*   send error. So, to prevent this, we set a flag to block any         */
  1099.     /*   further communication attempts.                                     */
  1100.     /*************************************************************************/
  1101.     pid     = GetEspProcessID();
  1102.     p       = GetPid( pid );
  1103.     mte     = p->mte;
  1104.     EntryPt = XSrvGetExeOrDllEntryOrExitPt( mte );
  1105.  
  1106.     XSrvNormalQuit( IsChildTerminated(), mte, EntryPt );
  1107.  
  1108.     CloseConnectSema4();
  1109.     /*************************************************************************/
  1110.     /* - At this                                                             */
  1111.     /*************************************************************************/
  1112.     ConnectClose( DEFAULT_HANDLE );
  1113.  
  1114.     memset( &Qelement, 0, sizeof(Qelement) );
  1115.     Qelement.ChildPid = pid;
  1116.     SendMsgToEspQue( ESP_QMSG_CHILD_TERM, &Qelement, sizeof(Qelement) );
  1117.  
  1118.     EndThread = TRUE;
  1119.    }
  1120.    break;
  1121.  
  1122.    case ESP_PROBE_TERM:
  1123.     /*************************************************************************/
  1124.     /* - At this point, thread 1 could be blocked in DosDebug().  When we    */
  1125.     /*   terminate the parent, then thread 1 may return and try return back  */
  1126.     /*   to the debugger resulting in a communications send error.  So, to   */
  1127.     /*   prevent this, we set a flag to block any further communication      */
  1128.     /*   attempts.                                                           */
  1129.     /*************************************************************************/
  1130.     SetHaltCommunicationsFlag();
  1131.     break;
  1132.  
  1133.    default:
  1134.     break;
  1135.   }
  1136.  
  1137.   /***************************************************************************/
  1138.   /* - Free the shared memory used for the message and initialize the        */
  1139.   /*   data element pointer for the next message.                            */
  1140.   /***************************************************************************/
  1141.   if( pDataAddr )
  1142.    DosFreeMem(pDataAddr);
  1143.  
  1144.   pDataAddr = NULL;
  1145.  }
  1146.  
  1147.  /****************************************************************************/
  1148.  /* - Come here to terminate the probe.                                      */
  1149.  /****************************************************************************/
  1150.  if( IsVerbose() ) {printf("\nProbe terminated");fflush(0);}
  1151.  exit(0);
  1152. }                                       /* end ReadQ().                      */
  1153.  
  1154. /*****************************************************************************/
  1155. /* SendMsgToEspTermQue()                                                     */
  1156. /*                                                                           */
  1157. /* Description:                                                              */
  1158. /*                                                                           */
  1159. /*  Send TRM_QMSG_xxxxxx message to a child debugger.                        */
  1160. /*                                                                           */
  1161. /* Parameters:                                                               */
  1162. /*                                                                           */
  1163. /*   Msg            TRM_QMSG_xxxxxx message.                                 */
  1164. /*   PQueElement    -> to optional queue element( buffer ).                  */
  1165. /*   QueElementLen  length of the queue element.                             */
  1166. /*                                                                           */
  1167. /* Return:                                                                   */
  1168. /*                                                                           */
  1169. /* Assumptions:                                                              */
  1170. /*                                                                           */
  1171. /*   The process id receiving the queue message is passed in the queue       */
  1172. /*   element.                                                                */
  1173. /*                                                                           */
  1174. /*****************************************************************************/
  1175. void SendMsgToEspTermQue(ULONG Msg , void *pQueElement, ULONG QueElementLen)
  1176. {
  1177.  USHORT   EspPid;
  1178.  ALLPIDS *p;
  1179.  char    *pQueName;
  1180.  
  1181.  /****************************************************************************/
  1182.  /* - At this time, we are not actually sending anything in a queue element. */
  1183.  /*   However, we're allowing for future expansion.                          */
  1184.  /****************************************************************************/
  1185.  
  1186.  /****************************************************************************/
  1187.  /* - Get a ptr to the shared memory structure of the queue owner.           */
  1188.  /****************************************************************************/
  1189.  EspPid = ((ESP_QUE_ELEMENT*)pQueElement)->ChildPid;
  1190.  p      = GetEspPid( EspPid );
  1191.  if( p )
  1192.  {
  1193.   pQueName = p->pTermQue;
  1194.   SendMsgToQue( pQueName, Msg, pQueElement, QueElementLen );
  1195.  }
  1196. }
  1197.  
  1198. /*****************************************************************************/
  1199. /* AddProcessToList()                                                        */
  1200. /* IsProcessInList()                                                         */
  1201. /*                                                                           */
  1202. /* Description:                                                              */
  1203. /*                                                                           */
  1204. /*   Maintain a list of new process notifications.                           */
  1205. /*                                                                           */
  1206. /* Parameters:                                                               */
  1207. /*                                                                           */
  1208. /*   NewPid      the new process id to be added to the list.                 */
  1209. /*                                                                           */
  1210. /* Return:                                                                   */
  1211. /*                                                                           */
  1212. /* Assumptions:                                                              */
  1213. /*                                                                           */
  1214. /*****************************************************************************/
  1215. static NEWPID *pNewPidList;
  1216. void AddProcessToList( USHORT NewPid )
  1217. {
  1218.  NEWPID *p;
  1219.  NEWPID *q;
  1220.  
  1221.  if( IsProcessInList(NewPid) == TRUE )
  1222.   return;
  1223.  
  1224.  q = Talloc(sizeof(NEWPID));
  1225.  
  1226.  memset(q, 0, sizeof(NEWPID) );
  1227.  
  1228.  q->pid = NewPid;
  1229.  
  1230.  for( p = (NEWPID*)&pNewPidList; p->next != NULL ; p = p->next ){;}
  1231.  
  1232.  p->next = q;
  1233.  
  1234.  return;
  1235. }
  1236.  
  1237. BOOL IsProcessInList( USHORT pid )
  1238. {
  1239.  NEWPID *p;
  1240.  
  1241.  for( p = pNewPidList ; p ; p = p->next )
  1242.   if( p->pid == pid )
  1243.    return(TRUE);
  1244.  
  1245.  return(FALSE);
  1246. }
  1247.