home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / switchto.zip / SwitchTo.cpp < prev    next >
Text File  |  1998-04-01  |  17KB  |  387 lines

  1. /***********************************************************************\
  2.  *                            SwitchTo.cpp                             *
  3.  *                 Copyright (C) by Stangl Roman, 1998                 *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed, under the conditions indicated in the documentation.       *
  6.  *                                                                     *
  7.  * SwitchTo.cpp SwitchTo/2 source file.                                *
  8.  *                                                                     *
  9.  * SwitchTo/2 switches to the Window List entry specified at the       *
  10.  * commandline with the following syntax:                              *
  11.  *                                                                     *
  12.  * Syntax:  SWITCHTO SessionName                                       *
  13.  * Where:   SessionName ... Name of Window List entry to switch to     * 
  14.  *                          causing it to get into foreground.         *
  15.  *                                                                     *
  16. \***********************************************************************/
  17.  
  18. /***********************************************************************\
  19.  * Technical Design:                                                   *
  20.  *                                                                     *
  21.  * This programs shows 2 ways to call the PM API from AVIO (advanced   *
  22.  * video), in other words commandline-based, programs. There are at    *
  23.  * least 2 methods how to do that:                                     *
  24.  * 1) The AVIO application can lanch a copy of itself and define that  *
  25.  *    that copy is started into a PM environment (by specifying that   *
  26.  *    to DosStartSession() or WinStartApp().                           *
  27.  * 2) The AVIO application can change its session type to PROG_PM, and *
  28.  *    while the PM environment is happy with that you can still view   *
  29.  *    the STDOUT output (e.g. when starting it from a command          *
  30.  *    processor).                                                      *
  31.  *                                                                     *
  32.  * The important point is that not the application's type defined in   *
  33.  * the executable (by the linker) is relevant if the PM environment    *
  34.  * can be initialized but the environment the application runs in.     *
  35. \***********************************************************************/
  36.  
  37. #pragma strings(readonly)
  38.  
  39. #include    <malloc.h>
  40. #include    <stdio.h>
  41. #include    <string.h>
  42.  
  43. #if defined(LAUNCHCOPY) || defined(CHANGETYPE)
  44. #else
  45.     #error Either macro LANCHCOPY or CHANGETYPE must be defined
  46.     #error Invoke NMAKE with parameters "LAUNCHCOPY=1" or "CHANGETYPE=1"
  47. #endif
  48.  
  49. #include    "SwitchTo.hpp"
  50.  
  51.                                         /* Required for PMPRINTF package, when used for
  52.                                            debugging as we're only using the Subsystem 
  53.                                            C Runtime library (we don't need the full blown
  54.                                            runtime, so let's save some space) */
  55. #ifdef  DEBUG
  56. long    time(long *ptimer)
  57. {
  58.     return(*ptimer);
  59. }
  60. #endif  /* DEBUG */
  61.  
  62. /****************************************************************************************\
  63.  * Class: SwitchTo                                                                      *
  64. \****************************************************************************************/
  65. /*--------------------------------------------------------------------------------------*\
  66.  * SwitchTo : Constructor(s)                                                            *
  67. \*--------------------------------------------------------------------------------------*/
  68. SwitchTo::SwitchTo(int argc, char *argv[]) :
  69.           iResult(ERR_NOERROR),
  70.           ulProcessType(0),
  71.           pcSessionName(0),
  72.           hab(0),
  73.           hmq(0),
  74.           hwndFrame(0),
  75.           hwndClient(0)
  76. {
  77.                                         /* Query environment including our process type */
  78.     checkEnvironment();
  79. #ifdef  LAUNCHCOPY
  80.     if(ulProcessType!=PROG_PM)
  81.         {
  82.         ULONG   ulMessageLength=0;
  83.  
  84.                                         /* If we're a non-PM process we are a windowcompatible
  85.                                            process so we can do printing to STDOUT */
  86.         displayMessage(NLSMSG_COPYRIGHT1);
  87.         displayMessage(NLSMSG_COPYRIGHT2);
  88.                                         /* The name of the session we want to switch into
  89.                                            foreground must be specified, otherwise we don't
  90.                                            know what to do */
  91.         if(argc!=2)
  92.             {
  93.             displayMessage(NLSMSG_USAGE1);
  94.             displayMessage(NLSMSG_USAGE2);
  95.             displayMessage(NLSMSG_USAGE3);
  96.             throw(ERR_SYNTAX);
  97.             }
  98.         else
  99.             {
  100.             pcSessionName=(char *)malloc(strlen(argv[1])+3);
  101.             if(strchr(argv[1], ' '))
  102.                 {
  103.                 strcpy(pcSessionName, "\"");
  104.                 strcat(pcSessionName, argv[1]);
  105.                 strcat(pcSessionName, "\"");
  106.                 }
  107.             else 
  108.                 strcpy(pcSessionName, argv[1]);
  109.             relaunchSelf();
  110.             free(pcSessionName);
  111.             pcSessionName=0;
  112.             }
  113.         }
  114.     else
  115.         {
  116.                                         /* If we're a PM process we can't do much except
  117.                                            PM calls, at least not printing to STDOUT (in the
  118.                                            sense that STDOUT does exists, but will not be
  119.                                            displayed on a window normally, e.g. redirection
  120.                                            is of course possible) */
  121.         if(argc!=2)
  122.             throw(ERR_SYNTAX);
  123.         else
  124.             {
  125.             int     iSwitchResult=0;
  126.  
  127.             pcSessionName=argv[1];
  128.             iSwitchResult=(int)switchtoApplication();
  129.             if(iSwitchResult!=NO_ERROR)
  130.                 throw(iSwitchResult);
  131.             }
  132.         }
  133. #elif   CHANGETYPE
  134.                                         /* If we're running as a windowed or fullscreen
  135.                                            AVIO session change our session type to PM */
  136.     if((ulProcessType==PROG_FULLSCREEN) || (ulProcessType==PROG_WINDOWABLEVIO))
  137.         {
  138.         ulProcessType=PROG_PM;
  139.         setProcessType(ulProcessType);
  140.         }
  141.                                         /* Now we're a PM process, but we can still output to
  142.                                            stdout, which will get displayed in the command 
  143.                                            window when launched from such a program */
  144.     displayMessage(NLSMSG_COPYRIGHT1);
  145.     displayMessage(NLSMSG_COPYRIGHT2);
  146.                                         /* The name of the session we want to switch into
  147.                                            foreground must be specified, otherwise we don't
  148.                                            know what to do */
  149.     if(argc!=2)
  150.         {
  151.         displayMessage(NLSMSG_USAGE1);
  152.         displayMessage(NLSMSG_USAGE2);
  153.         displayMessage(NLSMSG_USAGE3);
  154.         throw(ERR_SYNTAX);
  155.         }
  156.     else
  157.         {
  158.                                         /* Now switch to the requested application */
  159.         displayMessage(NLSMSG_INVOKE1, pcSessionName);
  160.         pcSessionName=argv[1];
  161.         iResult=(int)switchtoApplication();
  162.         if(iResult==NO_ERROR)
  163.             {
  164.             iResult=ERR_NOERROR;
  165.             displayMessage(NLSMSG_INVOKE3, pcSessionName);
  166.             }
  167.         else
  168.             {
  169.             iResult=ERR_SWITCHFAILED;
  170.             displayMessage(NLSMSG_INVOKE4, pcSessionName);
  171.             throw(iResult);
  172.             }
  173.         }
  174. #endif
  175. }
  176.  
  177. /*--------------------------------------------------------------------------------------*\
  178.  * SwitchTo : checkEnvironment(void)                                                    *
  179. \*--------------------------------------------------------------------------------------*/
  180. SwitchTo               &SwitchTo::checkEnvironment(void)
  181. {
  182.     TIB    *ptib;
  183.     PIB    *ppib;
  184.     char   *pcTemp;
  185.  
  186.                                         /* Get fully qualified path we were loaded from 
  187.                                            and save it */
  188.     DosGetInfoBlocks(&ptib, &ppib);
  189.     ulProcessType=ppib->pib_ultype;
  190.     DosQueryModuleName(ppib->pib_hmte, sizeof(acPathExecutable), acPathExecutable);
  191.     strcpy(acPathMessage, acPathExecutable);
  192.     pcTemp=strrchr(acPathMessage, '.');
  193.     if(pcTemp!=0)
  194.         strcpy(pcTemp, ".msg");    
  195.     return(*this);
  196. }
  197.  
  198. #ifdef  CHANGETYPE
  199. /*--------------------------------------------------------------------------------------*\
  200.  * SwitchTo : setProcessType(ULONG ulProcessType)                                       *
  201. \*--------------------------------------------------------------------------------------*/
  202. SwitchTo               &SwitchTo::setProcessType(ULONG ulProcessType)
  203. {
  204.     TIB    *ptib;
  205.     PIB    *ppib;
  206.     char   *pcTemp;
  207.  
  208.                                         /* Get process information block and change process
  209.                                            type */
  210.     DosGetInfoBlocks(&ptib, &ppib);
  211.     ppib->pib_ultype=ulProcessType;
  212.     return(*this);
  213. }
  214. #endif  /* CHANGETYPE */
  215.  
  216. #ifdef  LAUNCHCOPY
  217. /*--------------------------------------------------------------------------------------*\
  218.  * SwitchTo : relaunchSelf(char *pcSessionName)                                         *
  219. \*--------------------------------------------------------------------------------------*/
  220. SwitchTo               &SwitchTo::relaunchSelf(void)
  221. {
  222.     HQUEUE      hqueueSelf=0;
  223.     ULONG       ulPidSelf=0;
  224.     STARTDATA   startdataSelf;
  225.     char        acObjectBuffer[CCHMAXPATH];
  226.     PID         pidSelf=0;
  227.     ULONG       ulSessionIDSelf=0;
  228.     APIRET      apiretRc=NO_ERROR;
  229.     PSZ         pszBuffer=0;
  230.     REQUESTDATA requestdataSelf={ 0 };
  231.     ULONG       ulDataLen=0;
  232.     BYTE        bPriority=0;
  233.     RESULTCODE *presultcodeSelf;
  234.  
  235.     displayMessage(NLSMSG_INVOKE1, pcSessionName);
  236.                                         /* Create queue to receive return codes of our
  237.                                            PM instance into the VIO instance */
  238.     apiretRc=DosCreateQueue(&hqueueSelf, QUE_FIFO | QUE_CONVERT_ADDRESS, SWITCHTO_QUEUE);
  239.     apiretRc=DosOpenQueue(&ulPidSelf, &hqueueSelf, SWITCHTO_QUEUE);
  240.                                         /* Relaunch ourself but force a PM environment */
  241.     memset(&startdataSelf, 0, sizeof(startdataSelf));
  242.     startdataSelf.Length=sizeof(startdataSelf);
  243.     startdataSelf.Related=SSF_RELATED_CHILD;
  244.     startdataSelf.FgBg=SSF_FGBG_BACK;
  245.     startdataSelf.TraceOpt=SSF_TRACEOPT_NONE;
  246.     startdataSelf.PgmTitle="SwitchTo/2";
  247.     startdataSelf.PgmName=(PSZ)acPathExecutable;
  248.     startdataSelf.PgmInputs=(PBYTE)pcSessionName;    
  249.     startdataSelf.TermQ=SWITCHTO_QUEUE;
  250.     startdataSelf.Environment=0;    
  251.     startdataSelf.InheritOpt=SSF_INHERTOPT_SHELL;    
  252.     startdataSelf.SessionType=SSF_TYPE_PM;    
  253.     startdataSelf.ObjectBuffer=(PSZ)acObjectBuffer;    
  254.     startdataSelf.ObjectBuffLen=sizeof(acObjectBuffer);    
  255.     apiretRc=DosStartSession(&startdataSelf, &ulSessionIDSelf, &pidSelf);
  256.     if(apiretRc!=NO_ERROR)
  257.         displayMessage(NLSMSG_INVOKE2);
  258.     else
  259.         {
  260.         pszBuffer="";
  261.         requestdataSelf.pid=ulPidSelf;
  262.  
  263.         apiretRc=DosReadQueue(hqueueSelf, &requestdataSelf, &ulDataLen, (PPVOID)&pszBuffer,
  264.             0L, DCWW_WAIT, &bPriority, 0);
  265.                                         /* When the queue contains data to read
  266.                                            our PM instance has finished */
  267.         if(apiretRc==NO_ERROR)
  268.             {
  269.             presultcodeSelf=(RESULTCODE *)pszBuffer;
  270.  
  271.             if(presultcodeSelf->usCodeResult==NO_ERROR)
  272.                 {
  273.                 iResult=ERR_NOERROR;
  274.                 displayMessage(NLSMSG_INVOKE3, pcSessionName);
  275.                 }
  276.             else
  277.                 {
  278.                 iResult=ERR_SWITCHFAILED;
  279.                 displayMessage(NLSMSG_INVOKE4, pcSessionName);
  280.                 }
  281.             }
  282.         else
  283.             {
  284.             iResult=ERR_READINGQUEUE;
  285.             displayMessage(NLSMSG_INVOKE5);
  286.             }
  287.         DosFreeMem(pszBuffer);
  288.         }
  289.     apiretRc=DosCloseQueue(hqueueSelf);
  290.     return(*this);
  291. }
  292. #endif  /* LAUNCHCOPY */
  293.  
  294. /*--------------------------------------------------------------------------------------*\
  295.  * SwitchTo : switchtoApplication(void)                                                 *
  296. \*--------------------------------------------------------------------------------------*/
  297. ULONG                   SwitchTo::switchtoApplication(void)
  298. {
  299.     ULONG       ulRc=0;
  300.     ULONG       ulCount=0;
  301.     ULONG       ulIndex=0;
  302.     SWBLOCK    *pswblkCurrent=0;
  303.     SWENTRY    *pswentryCurrent=0;
  304.     ULONG       ulSwitchResult=PMERR_INVALID_SWITCH_HANDLE;
  305.     ULONG       flStyle=FCF_TITLEBAR | FCF_TASKLIST | FCF_SYSMENU;
  306.     QMSG        qmsg;
  307.  
  308.     hab=WinInitialize(0);
  309.     hmq=WinCreateMsgQueue(hab, 0);
  310.                                         /* Uncomment the following code an you will see a
  311.                                            sample window (which used the default window
  312.                                            procedure from PM, so the client won't draw)
  313.     WinRegisterClass(hab, "SwitchTo", WinDefWindowProc, 0, 0);
  314.     hwndFrame=WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &flStyle, "SwitchTo", "SwitchTo", 0, NULLHANDLE, 1, &hwndClient);
  315.     WinSetWindowPos(hwndFrame, HWND_TOP, 10, 10, 200, 200, SWP_SHOW | SWP_SIZE | SWP_MOVE | SWP_ZORDER);
  316.     WinShowWindow(hwndFrame, TRUE);
  317.     while(WinGetMsg(hab, &qmsg, 0, 0, 0))
  318.         WinDispatchMsg(hab, &qmsg);
  319.     WinDestroyWindow(hwndFrame);
  320.                                          */
  321.     ulCount=WinQuerySwitchList(hab, 0, 0);
  322.     pswblkCurrent=(PSWBLOCK)malloc(ulCount=((ulCount+1)*sizeof(SWENTRY)+sizeof(ULONG)));
  323.     ulCount=WinQuerySwitchList(hab, pswblkCurrent, ulCount);
  324.     for(ulIndex=0; ulIndex<ulCount; ulIndex++)
  325.         {
  326.         pswentryCurrent=&pswblkCurrent->aswentry[ulIndex];
  327. #ifdef  DEBUG
  328.         printf("Window List #%ld : %s\n", ulIndex, pswentryCurrent->swctl.szSwtitle);
  329. #endif
  330.         if(!strcmp(pswentryCurrent->swctl.szSwtitle, pcSessionName))
  331.             {
  332.             ulSwitchResult=WinSwitchToProgram(pswentryCurrent->hswitch);
  333.             break;
  334.             }
  335.         }
  336.     free(pswblkCurrent);
  337.     WinDestroyMsgQueue(hmq);
  338.     WinTerminate(hab);
  339.     return(ulSwitchResult);
  340. }
  341.  
  342. /*--------------------------------------------------------------------------------------*\
  343.  * SwitchTo : displayMessage(int iMessage)                                              *
  344. \*--------------------------------------------------------------------------------------*/
  345. SwitchTo               &SwitchTo::displayMessage(int iMessage, char *pcParameter)
  346. {
  347.                                         /* Table of message parameters */
  348.     char   *acParameters[]={ 0, 0 };
  349.     char    acMessage[2048]="";         /* Message text loaded from message file */
  350.     char   *pcMessageFormatted;         /* Message text formatted to common syntax */
  351.     ULONG   ulParameters=0;             /* Number of message parameters passed */
  352.     ULONG   ulMessageLength=0;          /* Length of loaded and parsed message */
  353.     APIRET  apiretRc=NO_ERROR;  
  354.  
  355.     if(pcParameter!=0)
  356.         acParameters[ulParameters++]=pcParameter;
  357.     apiretRc=DosGetMessage((CHAR **)acParameters, ulParameters, acMessage, 
  358.         sizeof(acMessage)-sizeof("SW20000: "), (ULONG)iMessage, 
  359.         (PSZ)acPathMessage, &ulMessageLength);
  360.     if(apiretRc!=NO_ERROR)
  361.         {
  362.         strcpy(acMessage, "SW20000E: Can't load message\r\n");
  363.         ulMessageLength=strlen(acMessage);
  364.         }
  365.     DosWrite(STDOUT, acMessage, ulMessageLength, &ulMessageLength);
  366.     return(*this);
  367. }
  368.  
  369. int     main(int argc, char *argv[])
  370. {
  371.     int         iResult=0;
  372.     SwitchTo   *pSwitchTo=0;
  373.  
  374.     try {
  375.         pSwitchTo=new SwitchTo(argc, argv);
  376.         }
  377.                                         /* Catch error and return with it */
  378.     catch (int iError)
  379.         {
  380.         DosExit(EXIT_PROCESS, (ULONG)iError);
  381.         }
  382.     iResult=pSwitchTo->iResult;
  383.     delete pSwitchTo;
  384.                                         /* Exit with return code 0 */
  385.     DosExit(EXIT_PROCESS, iResult);
  386. }
  387.