Annotation of q_a/samples/termq/termq.c, revision 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.