Annotation of q_a/samples/termq/termq.c, revision 1.1.1.1

1.1       root        1: 
                      2:   /******************************************************************
                      3:   * This program demonstrates how convert an OS/2 program that uses *
                      4:   * termination queues to wait for multiple child processses to     *
                      5:   * terminate. This is done under Win32 by waiting for the newly    *
                      6:   * created child process handles to be signalled.                  *
                      7:   *                                                                 *
                      8:   * This program demonstrates the use of the following Win32 APIs:  *
                      9:   *   CreateProcess, WaitForMultipleObjects, GetExitCodeProcess.    *
                     10:   ******************************************************************/
                     11: 
                     12: #include <windows.h>
                     13: #include <stdio.h>
                     14: #include <stdlib.h>
                     15: 
                     16: #define PERR(api) printf("%s: Error %d from %s on line %d\n",  \
                     17:     __FILE__, GetLastError(), api, __LINE__);
                     18: 
                     19: #define PROCESS_COUNT 3
                     20: 
                     21: int main()
                     22: {
                     23:   /*****************************************************************
                     24:   * The following are the OS/2 types used in the OS/2 version:     *
                     25:   *                                                                *
                     26:   * USHORT usErr;                                                  *
                     27:   * HQUEUE hQueue;                                                 *
                     28:   * STARTDATA stdata;                                              *
                     29:   * QUEUERESULT qresc;                                             *
                     30:   * USHORT cbElement, i, idSession;                                *
                     31:   * PUSHORT pusQelemBuf;                                           *
                     32:   * BYTE bElemPrty;                                                *
                     33:   * USHORT pid;                                                    *
                     34:   *****************************************************************/
                     35: 
                     36:   STARTUPINFO stdata;  /* info for CreateProcess */
                     37:   BOOL fSuccess;  /* Win32 API return code */
                     38:   PROCESS_INFORMATION ppi;  /* info for CreateProcess */
                     39:   DWORD adwProcessId[PROCESS_COUNT];  /* array of process ID's */
                     40:   HANDLE ahProcess[PROCESS_COUNT];  /* array of process handles */
                     41:   DWORD dwResult;  /* API result */
                     42:   DWORD dwExitCode;  /* exit code from the new processes */
                     43:   int i, j;
                     44: 
                     45:   /*******************************************************************
                     46:   * usErr = DosCreateQueue(&hQueue, QUE_FIFO, szTermQName);          *
                     47:   * assert(!usErr);                                                  *
                     48:   *                                                                  *
                     49:   *   Rather than use a queue mechanism to both signal us that the   *
                     50:   *   child process has ended and to return an exit code with, under *
                     51:   *   Win32 we need to wait for the process object to be signalled,  *
                     52:   *   then call GetExitCodeProcess to get the exit code.             *
                     53:   *******************************************************************/
                     54: 
                     55:   /******************************************************************
                     56:   *   In the original OS/2 version, the variable stdata is of type  *
                     57:   *   STARTDATA. In this version, it is of type STARTUPINFO. In the *
                     58:   *   comment boxes I will show the OS/2 settings for the STARTDATA *
                     59:   *   structure. Following the comment will be the Win32 equivalent *
                     60:   *   setting, if any.                                              *
                     61:   *                                                                 *
                     62:   * stdata.Related = TRUE;                                          *
                     63:   *                                                                 *
                     64:   *   Under Win32 there is no formal parent/child process           *
                     65:   *   relationship between processes and no equivalent parameter to *
                     66:   *   set.                                                          *
                     67:   *                                                                 *
                     68:   * stdata.TraceOpt = 0;                                            *
                     69:   *                                                                 *
                     70:   *   If the new process was to be debugged under Win32, you would  *
                     71:   *   set the DEBUG_PROCESS flag for the fdwCreate parameter for    *
                     72:   *   CreateProcess.                                                *
                     73:   *                                                                 *
                     74:   * stdata.PgmTitle = "OS/2 Command Processor";                     *
                     75:   ******************************************************************/
                     76: 
                     77:   stdata.lpTitle = "Win32 Command Processor";
                     78: 
                     79:   /*******************************************************************
                     80:   * stdata.PgmName = "c:\\os2\\cmd.exe";                             *
                     81:   * stdata.PgmInputs = NULL;                                         *
                     82:   *                                                                  *
                     83:   *   The equivalent Win32 parameters are passed directly into       *
                     84:   *   CreateProcess as the lpszImageName and lpszCommandLine         *
                     85:   *   parameters.                                                    *
                     86:   *                                                                  *
                     87:   * stdata.TermQ = szTermQName;                                      *
                     88:   *                                                                  *
                     89:   *   Wait for the object process to be signalled in Win32 instead   *
                     90:   *   of using queues under OS/2.                                    *
                     91:   *                                                                  *
                     92:   * stdata.Environment = NULL;                                       *
                     93:   *                                                                  *
                     94:   *   In Win32, this is passed as a parameter to CreateProcess as    *
                     95:   *   the lpvEnvironment parameter.                                  *
                     96:   *                                                                  *
                     97:   * stdata.InheritOpt = 0;                                           *
                     98:   *                                                                  *
                     99:   *   Though there is no formal parent/child relationship between    *
                    100:   *   two processes in Win32, process can have the new process       *
                    101:   *   inherit open object handles by specifying TRUE for the         *
                    102:   *   fInheritHandles flag for CreateProcess.                        *
                    103:   *                                                                  *
                    104:   * stdata.SessionType = 2;                                          *
                    105:   *                                                                  *
                    106:   *   In Win32, the sessiontype does not need to be specified. It    *
                    107:   *   will be automatically determined.                              *
                    108:   *                                                                  *
                    109:   * stdata.IconFile = NULL;                                          *
                    110:   * stdata.PgmHandle = 0;                                            *
                    111:   *                                                                  *
                    112:   *   In Win32, no similar options exist.                            *
                    113:   *                                                                  *
                    114:   * stdata.PgmControl = 32768;                                       *
                    115:   * stdata.InitXPos = 50;                                            *
                    116:   * stdata.InitYPos = 250;                                           *
                    117:   * stdata.InitXSize = 200;                                          *
                    118:   * stdata.InitYSize = 100;                                          *
                    119:   *                                                                  *
                    120:   *   For console apps under Win32, you can specify the console size *
                    121:   *   in terms of characters instead of pixel positions.             *
                    122:   *******************************************************************/
                    123: 
                    124:   stdata.dwX = 50; /* X starting position (pixels) */
                    125:   stdata.dwY = 50; /* X starting position (pixels) */
                    126:   stdata.dwXSize = 40;
                    127:   stdata.dwYSize = 25;
                    128: 
                    129:   /* set additional parameters for Win32 CreateProcess call */
                    130:   stdata.cb = sizeof(stdata);
                    131:   stdata.lpReserved = NULL;
                    132:   stdata.lpDesktop = NULL;
                    133:   stdata.dwFlags = 0;  /* attributes for starting process */
                    134:   stdata.wShowWindow = 0;
                    135:   stdata.cbReserved2 = 0;
                    136:   stdata.lpReserved2 = NULL;
                    137: 
                    138:   /* start PROCESS_COUNT number of child sessions */
                    139:   for (i = 0; i < PROCESS_COUNT; i++)
                    140:     {
                    141:     /**************************************************
                    142:     * DosStartSession(&stdata, &idSession, &pid);     *
                    143:     *                                                 *
                    144:     * Replace this with the Win32 CreateProcess call. *
                    145:     **************************************************/
                    146: 
                    147:     fSuccess = CreateProcess(NULL,  /* image name */
                    148:         "cmd.exe",  /* program to run and command line */
                    149:         NULL,  /* security attributes for new process */
                    150:         NULL,  /* security attributes for new thread */
                    151:         FALSE,  /* don't inherit open object handles */
                    152:         NORMAL_PRIORITY_CLASS | /* creation flags */
                    153:         CREATE_NEW_CONSOLE, /* creation flags - new console for process */
                    154:         NULL,  /* use environment of this process for new process */
                    155:         NULL,  /* use current directory for startup directory */
                    156:         &stdata,  /* startup data structure */
                    157:         &ppi);  /* process info from the call */
                    158:      if (!fSuccess)
                    159:       PERR("CreateProcess");
                    160:     CloseHandle(ppi.hThread);  /* we don't need this handle */
                    161: 
                    162:     /********************************************************
                    163:     * printf("session id = %d started\n", idSession);       *
                    164:     *                                                       *
                    165:     *   In Win32 the session ID is contained in the         *
                    166:     *   PROCESS_INFORMATION structure (variable ppi in this *
                    167:     *   example).                                           *
                    168:     ********************************************************/
                    169: 
                    170:     printf("session id = %d started\n", ppi.dwProcessId);
                    171:     ahProcess[i] = ppi.hProcess;  /* save the process handles */
                    172:     adwProcessId[i] = ppi.dwProcessId;  /* save process IDs */
                    173:     stdata.dwX += 50;  /* shift next window to cascade */
                    174:     stdata.dwY += 50;
                    175:     }
                    176: 
                    177:   /******************************************************************
                    178:   * for (i = 0; i < PROCESS_COUNT; i++)                             *
                    179:   *   {                                                             *
                    180:   *   usErr = DosReadQueue(hQueue, &qresc, &cbElement,              *
                    181:   *       (PVOID FAR *) &pusQelemBuf, 0, DCWW_WAIT, &bElemPrty, 0); *
                    182:   *   assert(!usErr);                                               *
                    183:   *   printf("queue return: session id = %d, resultcode = %d\n",    *
                    184:   *       pusQelemBuf[0], pusQelemBuf[1]);                          *
                    185:   *   usErr = DosFreeSeg(SELECTOROF(pusQelemBuf));                  *
                    186:   *   assert(!usErr);                                               *
                    187:   *   }                                                             *
                    188:   *                                                                 *
                    189:   *   Rather than read from the termination queue, under Win32 we   *
                    190:   *   wait for any of the returned process handles to be signalled. *
                    191:   *   We must also use GetExitCodeProcess to get the exit codes     *
                    192:   *   rather than getting them from the queue packet.               *
                    193:   ******************************************************************/
                    194: 
                    195:   for (i = 0; i < PROCESS_COUNT; i++)
                    196:     {
                    197:     dwResult = WaitForMultipleObjects(
                    198:         PROCESS_COUNT - i,  /* number of objects to wait on */
                    199:         ahProcess,  /* array of object handles to wait on */
                    200:         FALSE,  /* wait on any handle to signal, rather than all */
                    201:         (DWORD) -1);  /* timeout (wait forever) */
                    202:     if (dwResult == -1)
                    203:       PERR("WaitForMultipleObjects");
                    204:     dwResult -= WAIT_OBJECT_0; /* adjust to zero-based range */
                    205:     fSuccess = GetExitCodeProcess(
                    206:         ahProcess[dwResult],  /* process handle */
                    207:         &dwExitCode);  /* returned exit code */
                    208:     if (!fSuccess)
                    209:       PERR("GetExitCodeProcess");
                    210:     CloseHandle(ahProcess[dwResult]);
                    211:     printf("process return: session id = %d, result code = %d\n",
                    212:         adwProcessId[dwResult], dwExitCode);
                    213:     /* now we need to compact the handle/process ID arrays to remove */
                    214:     /* closed handle slots */
                    215:     for (j = dwResult; j <= PROCESS_COUNT - i - 2; j++)
                    216:       {
                    217:       /* shift remaining process handles down one slot */
                    218:       ahProcess[j] = ahProcess[j + 1];
                    219:       /* shift remaining process IDs down one slot */
                    220:       adwProcessId[j] = adwProcessId[j + 1];
                    221:       }
                    222:     }
                    223:   return(0);
                    224: }

unix.superglobalmegacorp.com

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