File:  [WindowsNT SDKs] / q_a / samples / termq / termq.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:29:19 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntsdk-oct-1992, ntsdk-jun-1992, HEAD
Microsoft Windows NT Build 297 06-28-1992


  /******************************************************************
  * This program demonstrates how convert an OS/2 program that uses *
  * termination queues to wait for multiple child processses to     *
  * terminate. This is done under Win32 by waiting for the newly    *
  * created child process handles to be signalled.                  *
  *                                                                 *
  * This program demonstrates the use of the following Win32 APIs:  *
  *   CreateProcess, WaitForMultipleObjects, GetExitCodeProcess.    *
  ******************************************************************/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define PERR(api) printf("%s: Error %d from %s on line %d\n",  \
    __FILE__, GetLastError(), api, __LINE__);

#define PROCESS_COUNT 3

int main()
{
  /*****************************************************************
  * The following are the OS/2 types used in the OS/2 version:     *
  *                                                                *
  * USHORT usErr;                                                  *
  * HQUEUE hQueue;                                                 *
  * STARTDATA stdata;                                              *
  * QUEUERESULT qresc;                                             *
  * USHORT cbElement, i, idSession;                                *
  * PUSHORT pusQelemBuf;                                           *
  * BYTE bElemPrty;                                                *
  * USHORT pid;                                                    *
  *****************************************************************/

  STARTUPINFO stdata;  /* info for CreateProcess */
  BOOL fSuccess;  /* Win32 API return code */
  PROCESS_INFORMATION ppi;  /* info for CreateProcess */
  DWORD adwProcessId[PROCESS_COUNT];  /* array of process ID's */
  HANDLE ahProcess[PROCESS_COUNT];  /* array of process handles */
  DWORD dwResult;  /* API result */
  DWORD dwExitCode;  /* exit code from the new processes */
  int i, j;

  /*******************************************************************
  * usErr = DosCreateQueue(&hQueue, QUE_FIFO, szTermQName);          *
  * assert(!usErr);                                                  *
  *                                                                  *
  *   Rather than use a queue mechanism to both signal us that the   *
  *   child process has ended and to return an exit code with, under *
  *   Win32 we need to wait for the process object to be signalled,  *
  *   then call GetExitCodeProcess to get the exit code.             *
  *******************************************************************/

  /******************************************************************
  *   In the original OS/2 version, the variable stdata is of type  *
  *   STARTDATA. In this version, it is of type STARTUPINFO. In the *
  *   comment boxes I will show the OS/2 settings for the STARTDATA *
  *   structure. Following the comment will be the Win32 equivalent *
  *   setting, if any.                                              *
  *                                                                 *
  * stdata.Related = TRUE;                                          *
  *                                                                 *
  *   Under Win32 there is no formal parent/child process           *
  *   relationship between processes and no equivalent parameter to *
  *   set.                                                          *
  *                                                                 *
  * stdata.TraceOpt = 0;                                            *
  *                                                                 *
  *   If the new process was to be debugged under Win32, you would  *
  *   set the DEBUG_PROCESS flag for the fdwCreate parameter for    *
  *   CreateProcess.                                                *
  *                                                                 *
  * stdata.PgmTitle = "OS/2 Command Processor";                     *
  ******************************************************************/

  stdata.lpTitle = "Win32 Command Processor";

  /*******************************************************************
  * stdata.PgmName = "c:\\os2\\cmd.exe";                             *
  * stdata.PgmInputs = NULL;                                         *
  *                                                                  *
  *   The equivalent Win32 parameters are passed directly into       *
  *   CreateProcess as the lpszImageName and lpszCommandLine         *
  *   parameters.                                                    *
  *                                                                  *
  * stdata.TermQ = szTermQName;                                      *
  *                                                                  *
  *   Wait for the object process to be signalled in Win32 instead   *
  *   of using queues under OS/2.                                    *
  *                                                                  *
  * stdata.Environment = NULL;                                       *
  *                                                                  *
  *   In Win32, this is passed as a parameter to CreateProcess as    *
  *   the lpvEnvironment parameter.                                  *
  *                                                                  *
  * stdata.InheritOpt = 0;                                           *
  *                                                                  *
  *   Though there is no formal parent/child relationship between    *
  *   two processes in Win32, process can have the new process       *
  *   inherit open object handles by specifying TRUE for the         *
  *   fInheritHandles flag for CreateProcess.                        *
  *                                                                  *
  * stdata.SessionType = 2;                                          *
  *                                                                  *
  *   In Win32, the sessiontype does not need to be specified. It    *
  *   will be automatically determined.                              *
  *                                                                  *
  * stdata.IconFile = NULL;                                          *
  * stdata.PgmHandle = 0;                                            *
  *                                                                  *
  *   In Win32, no similar options exist.                            *
  *                                                                  *
  * stdata.PgmControl = 32768;                                       *
  * stdata.InitXPos = 50;                                            *
  * stdata.InitYPos = 250;                                           *
  * stdata.InitXSize = 200;                                          *
  * stdata.InitYSize = 100;                                          *
  *                                                                  *
  *   For console apps under Win32, you can specify the console size *
  *   in terms of characters instead of pixel positions.             *
  *******************************************************************/

  stdata.dwX = 50; /* X starting position (pixels) */
  stdata.dwY = 50; /* X starting position (pixels) */
  stdata.dwXSize = 40;
  stdata.dwYSize = 25;

  /* set additional parameters for Win32 CreateProcess call */
  stdata.cb = sizeof(stdata);
  stdata.lpReserved = NULL;
  stdata.lpDesktop = NULL;
  stdata.dwFlags = 0;  /* attributes for starting process */
  stdata.wShowWindow = 0;
  stdata.cbReserved2 = 0;
  stdata.lpReserved2 = NULL;

  /* start PROCESS_COUNT number of child sessions */
  for (i = 0; i < PROCESS_COUNT; i++)
    {
    /**************************************************
    * DosStartSession(&stdata, &idSession, &pid);     *
    *                                                 *
    * Replace this with the Win32 CreateProcess call. *
    **************************************************/

    fSuccess = CreateProcess(NULL,  /* image name */
        "cmd.exe",  /* program to run and command line */
        NULL,  /* security attributes for new process */
        NULL,  /* security attributes for new thread */
        FALSE,  /* don't inherit open object handles */
        NORMAL_PRIORITY_CLASS | /* creation flags */
        CREATE_NEW_CONSOLE, /* creation flags - new console for process */
        NULL,  /* use environment of this process for new process */
        NULL,  /* use current directory for startup directory */
        &stdata,  /* startup data structure */
        &ppi);  /* process info from the call */
     if (!fSuccess)
      PERR("CreateProcess");
    CloseHandle(ppi.hThread);  /* we don't need this handle */

    /********************************************************
    * printf("session id = %d started\n", idSession);       *
    *                                                       *
    *   In Win32 the session ID is contained in the         *
    *   PROCESS_INFORMATION structure (variable ppi in this *
    *   example).                                           *
    ********************************************************/

    printf("session id = %d started\n", ppi.dwProcessId);
    ahProcess[i] = ppi.hProcess;  /* save the process handles */
    adwProcessId[i] = ppi.dwProcessId;  /* save process IDs */
    stdata.dwX += 50;  /* shift next window to cascade */
    stdata.dwY += 50;
    }

  /******************************************************************
  * for (i = 0; i < PROCESS_COUNT; i++)                             *
  *   {                                                             *
  *   usErr = DosReadQueue(hQueue, &qresc, &cbElement,              *
  *       (PVOID FAR *) &pusQelemBuf, 0, DCWW_WAIT, &bElemPrty, 0); *
  *   assert(!usErr);                                               *
  *   printf("queue return: session id = %d, resultcode = %d\n",    *
  *       pusQelemBuf[0], pusQelemBuf[1]);                          *
  *   usErr = DosFreeSeg(SELECTOROF(pusQelemBuf));                  *
  *   assert(!usErr);                                               *
  *   }                                                             *
  *                                                                 *
  *   Rather than read from the termination queue, under Win32 we   *
  *   wait for any of the returned process handles to be signalled. *
  *   We must also use GetExitCodeProcess to get the exit codes     *
  *   rather than getting them from the queue packet.               *
  ******************************************************************/

  for (i = 0; i < PROCESS_COUNT; i++)
    {
    dwResult = WaitForMultipleObjects(
        PROCESS_COUNT - i,  /* number of objects to wait on */
        ahProcess,  /* array of object handles to wait on */
        FALSE,  /* wait on any handle to signal, rather than all */
        (DWORD) -1);  /* timeout (wait forever) */
    if (dwResult == -1)
      PERR("WaitForMultipleObjects");
    dwResult -= WAIT_OBJECT_0; /* adjust to zero-based range */
    fSuccess = GetExitCodeProcess(
        ahProcess[dwResult],  /* process handle */
        &dwExitCode);  /* returned exit code */
    if (!fSuccess)
      PERR("GetExitCodeProcess");
    CloseHandle(ahProcess[dwResult]);
    printf("process return: session id = %d, result code = %d\n",
        adwProcessId[dwResult], dwExitCode);
    /* now we need to compact the handle/process ID arrays to remove */
    /* closed handle slots */
    for (j = dwResult; j <= PROCESS_COUNT - i - 2; j++)
      {
      /* shift remaining process handles down one slot */
      ahProcess[j] = ahProcess[j + 1];
      /* shift remaining process IDs down one slot */
      adwProcessId[j] = adwProcessId[j + 1];
      }
    }
  return(0);
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.