Ignore:
Timestamp:
Mar 27, 2002, 9:27:02 PM (23 years ago)
Author:
umoeller
Message:

Sources as of 0.9.18.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/apps.c

    r151 r152  
    3333
    3434#define INCL_DOSPROCESS
     35#define INCL_DOSEXCEPTIONS
    3536#define INCL_DOSMODULEMGR
    3637#define INCL_DOSSESMGR
     
    4344
    4445#include <stdio.h>
     46#include <setjmp.h>             // needed for except.h
     47#include <assert.h>             // needed for except.h
    4548
    4649#include "setup.h"                      // code generation and debugging options
     
    4851#include "helpers\apps.h"
    4952#include "helpers\dosh.h"
     53#include "helpers\except.h"             // exception handling
    5054#include "helpers\prfh.h"
    5155#include "helpers\standards.h"          // some standard macros
     
    556560
    557561APIRET appQueryAppType(const char *pcszExecutable,
    558                        PULONG pulDosAppType,
    559                        PULONG pulWinAppType)
     562                       PULONG pulDosAppType,            // out: DOS app type
     563                       PULONG pulWinAppType)            // out: PROG_* app type
    560564{
    561565    APIRET arc;
     
    875879}
    876880
     881#ifdef _PMPRINTF_
     882
     883static void DumpMemoryBlock(PBYTE pb,       // in: start address
     884                     ULONG ulSize,   // in: size of block
     885                     ULONG ulIndent) // in: how many spaces to put
     886                                     //     before each output line
     887{
     888    TRY_QUIET(excpt1)
     889    {
     890        PBYTE   pbCurrent = pb;                 // current byte
     891        ULONG   ulCount = 0,
     892                ulCharsInLine = 0;              // if this grows > 7, a new line is started
     893        CHAR    szTemp[1000];
     894        CHAR    szLine[400] = "",
     895                szAscii[30] = "         ";      // ASCII representation; filled for every line
     896        PSZ     pszLine = szLine,
     897                pszAscii = szAscii;
     898
     899        for (pbCurrent = pb;
     900             ulCount < ulSize;
     901             pbCurrent++, ulCount++)
     902        {
     903            if (ulCharsInLine == 0)
     904            {
     905                memset(szLine, ' ', ulIndent);
     906                pszLine += ulIndent;
     907            }
     908            pszLine += sprintf(pszLine, "%02lX ", (ULONG)*pbCurrent);
     909
     910            if ( (*pbCurrent > 31) && (*pbCurrent < 127) )
     911                // printable character:
     912                *pszAscii = *pbCurrent;
     913            else
     914                *pszAscii = '.';
     915            pszAscii++;
     916
     917            ulCharsInLine++;
     918            if (    (ulCharsInLine > 7)         // 8 bytes added?
     919                 || (ulCount == ulSize-1)       // end of buffer reached?
     920               )
     921            {
     922                // if we haven't had eight bytes yet,
     923                // fill buffer up to eight bytes with spaces
     924                ULONG   ul2;
     925                for (ul2 = ulCharsInLine;
     926                     ul2 < 8;
     927                     ul2++)
     928                    pszLine += sprintf(pszLine, "   ");
     929
     930                sprintf(szTemp, "%04lX:  %s  %ss",
     931                                (ulCount & 0xFFFFFFF8),  // offset in hex
     932                                szLine,         // bytes string
     933                                szAscii);       // ASCII string
     934
     935                _Pmpf(("%s", szTemp));
     936
     937                // restart line buffer
     938                pszLine = szLine;
     939
     940                // clear ASCII buffer
     941                strcpy(szAscii, "         ");
     942                pszAscii = szAscii;
     943
     944                // reset line counter
     945                ulCharsInLine = 0;
     946            }
     947        }
     948
     949    }
     950    CATCH(excpt1)
     951    {
     952        _Pmpf(("Crash in " __FUNCTION__ ));
     953    } END_CATCH();
     954}
     955
     956#endif
     957
     958/*
     959 *@@ appFixProgDetails:
     960 *      extracted code from appStartApp to fix the
     961 *      given PROGDETAILS data to support the typical
     962 *      WPS stuff.
     963 *
     964 *      This is now used by XWP's progOpenProgram
     965 *      directly as a temporary fix for all the
     966 *      session hangs.
     967 *
     968 *      The caller is responsible for cleaning out
     969 *      the given three memory buffers.
     970 *
     971 *@@added V0.9.18 (2002-03-27) [umoeller]
     972 */
     973
     974APIRET appFixProgDetails(PPROGDETAILS pDetails,             // out: fixed program spec (req.)
     975                         const PROGDETAILS *pcProgDetails,  // in: program spec (req.)
     976                         ULONG ulFlags,                     // in: APP_RUN_* flags or 0
     977                         PXSTRING pstrExecutablePatched,    // in: init'ed XSTRING, out: to be freed
     978                         PXSTRING pstrParamsPatched,        // in: init'ed XSTRING, out: to be freed
     979                         PSZ *ppszWinOS2Env)                // in: ptr to NULL, out: memory to be freed
     980{
     981    APIRET          arc = NO_ERROR;
     982
     983    memcpy(pDetails, pcProgDetails, sizeof(PROGDETAILS));
     984            // pointers still point into old prog details buffer
     985    pDetails->Length = sizeof(PROGDETAILS);
     986    pDetails->progt.fbVisible = SHE_VISIBLE;
     987
     988    // all this only makes sense if this contains something...
     989    // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller]
     990    if (    (!pDetails->pszExecutable)
     991         || (!(*(pDetails->pszExecutable)))
     992       )
     993        arc = ERROR_INVALID_PARAMETER;
     994    else
     995    {
     996        ULONG           ulIsWinApp;
     997
     998        // memset(&pDetails->swpInitial, 0, sizeof(SWP));
     999        // this wasn't a good idea... WPProgram stores stuff
     1000        // in here, such as the "minimize on startup" -> SWP_MINIMIZE
     1001
     1002        // duplicate parameters...
     1003        // we need this for string manipulations below...
     1004        if (    (pDetails->pszParameters)
     1005             && (*pDetails->pszParameters)    // V0.9.18
     1006           )
     1007            xstrcpy(pstrParamsPatched,
     1008                    pDetails->pszParameters,
     1009                    0);
     1010
     1011        #ifdef DEBUG_PROGRAMSTART
     1012            _Pmpf((__FUNCTION__ ": old progc: 0x%lX", pcProgDetails->progt.progc));
     1013            _Pmpf(("  pszTitle: %s", (pDetails->pszTitle) ? pDetails->pszTitle : NULL));
     1014            _Pmpf(("  pszIcon: %s", (pDetails->pszIcon) ? pDetails->pszIcon : NULL));
     1015        #endif
     1016
     1017        // program type fixups
     1018        switch (pDetails->progt.progc)        // that's a ULONG
     1019        {
     1020            case ((ULONG)-1):       // we get that sometimes...
     1021            case PROG_DEFAULT:
     1022            {
     1023                // V0.9.12 (2001-05-26) [umoeller]
     1024                ULONG ulDosAppType;
     1025                appQueryAppType(pDetails->pszExecutable,
     1026                                &ulDosAppType,
     1027                                &pDetails->progt.progc);
     1028            }
     1029            break;
     1030        }
     1031
     1032        // set session type from option flags
     1033        if (ulFlags & APP_RUN_FULLSCREEN)
     1034        {
     1035            if (pDetails->progt.progc == PROG_WINDOWABLEVIO)
     1036                pDetails->progt.progc = PROG_FULLSCREEN;
     1037            else if (pDetails->progt.progc == PROG_WINDOWEDVDM)
     1038                pDetails->progt.progc = PROG_VDM;
     1039        }
     1040
     1041        if (ulIsWinApp = appIsWindowsApp(pDetails->progt.progc))
     1042        {
     1043            if (ulFlags & APP_RUN_FULLSCREEN)
     1044                pDetails->progt.progc = (ulFlags & APP_RUN_ENHANCED)
     1045                                                ? PROG_31_ENH
     1046                                                : PROG_31_STD;
     1047            else
     1048            {
     1049                if (ulFlags & APP_RUN_STANDARD)
     1050                    pDetails->progt.progc = (ulFlags & APP_RUN_SEPARATE)
     1051                                                ? PROG_31_STDSEAMLESSVDM
     1052                                                : PROG_31_STDSEAMLESSCOMMON;
     1053                else if (ulFlags & APP_RUN_ENHANCED)
     1054                    pDetails->progt.progc = (ulFlags & APP_RUN_SEPARATE)
     1055                                                ? PROG_31_ENHSEAMLESSVDM
     1056                                                : PROG_31_ENHSEAMLESSCOMMON;
     1057            }
     1058
     1059            // re-run V0.9.16 (2001-10-19) [umoeller]
     1060            ulIsWinApp = appIsWindowsApp(pDetails->progt.progc);
     1061        }
     1062
     1063        if (!arc)
     1064        {
     1065            /*
     1066             * command lines fixups:
     1067             *
     1068             */
     1069
     1070            if (!strcmp(pDetails->pszExecutable, "*"))
     1071            {
     1072                /*
     1073                 * "*" for command sessions:
     1074                 *
     1075                 */
     1076
     1077                if (ulIsWinApp == 2)
     1078                {
     1079                    // enhanced Win-OS/2 session:
     1080                    PSZ psz = NULL;
     1081                    if (pstrParamsPatched->ulLength)
     1082                        // "/3 " + existing params
     1083                        psz = strdup(pstrParamsPatched->psz);
     1084
     1085                    xstrcpy(pstrParamsPatched, "/3 ", 0);
     1086
     1087                    if (psz)
     1088                    {
     1089                        xstrcat(pstrParamsPatched, psz, 0);
     1090                        free(psz);
     1091                    }
     1092                }
     1093
     1094                if (ulIsWinApp)
     1095                {
     1096                    // cheat: WinStartApp doesn't support NULL
     1097                    // for Win-OS2 sessions, so manually start winos2.com
     1098                    pDetails->pszExecutable = "WINOS2.COM";
     1099                    // this is a DOS app, so fix this to DOS fullscreen
     1100                    pDetails->progt.progc = PROG_VDM;
     1101                }
     1102                else
     1103                    // for all other executable types
     1104                    // (including OS/2 and DOS sessions),
     1105                    // set pszExecutable to NULL; this will
     1106                    // have WinStartApp start a cmd shell
     1107                    pDetails->pszExecutable = NULL;
     1108
     1109            } // end if (strcmp(pProgDetails->pszExecutable, "*") == 0)
     1110            else
     1111            {
     1112                // check if the executable is fully qualified; if so,
     1113                // check if the executable file exists
     1114                if (    (pDetails->pszExecutable[1] == ':')
     1115                     && (strchr(pDetails->pszExecutable, '\\'))
     1116                   )
     1117                {
     1118                    ULONG ulAttr;
     1119                    if (!(arc = doshQueryPathAttr(pDetails->pszExecutable,
     1120                                                  &ulAttr)))
     1121                    {
     1122                        // make sure startup dir is really a directory
     1123                        if (pDetails->pszStartupDir)
     1124                        {
     1125                            // it is valid to specify a startup dir of "C:"
     1126                            if (    (strlen(pDetails->pszStartupDir) > 2)
     1127                                 && (!(arc = doshQueryPathAttr(pDetails->pszStartupDir,
     1128                                                               &ulAttr)))
     1129                                 && (!(ulAttr & FILE_DIRECTORY))
     1130                               )
     1131                                arc = ERROR_PATH_NOT_FOUND;
     1132                        }
     1133                    }
     1134                }
     1135                else
     1136                {
     1137                    // _not_ fully qualified: look it up on the PATH then
     1138                    // V0.9.16 (2001-12-06) [umoeller]
     1139                    CHAR    szFQExecutable[CCHMAXPATH];
     1140                    if (!(arc = doshSearchPath("PATH",
     1141                                               pDetails->pszExecutable,
     1142                                               szFQExecutable,
     1143                                               sizeof(szFQExecutable))))
     1144                    {
     1145                        // alright, found it:
     1146                        xstrcpy(pstrExecutablePatched, szFQExecutable, 0);
     1147                        pDetails->pszExecutable = pstrExecutablePatched->psz;
     1148                    }
     1149                }
     1150
     1151                if (!arc)
     1152                {
     1153                    PSZ pszExtension;
     1154                    switch (pDetails->progt.progc)
     1155                    {
     1156                        /*
     1157                         *  .CMD files fixups
     1158                         *
     1159                         */
     1160
     1161                        case PROG_FULLSCREEN:       // OS/2 fullscreen
     1162                        case PROG_WINDOWABLEVIO:    // OS/2 window
     1163                        {
     1164                            if (    (pszExtension = doshGetExtension(pDetails->pszExecutable))
     1165                                 && (!stricmp(pszExtension, "CMD"))
     1166                               )
     1167                            {
     1168                                CallBatchCorrectly(pDetails,
     1169                                                   pstrParamsPatched,
     1170                                                   "OS2_SHELL",
     1171                                                   "CMD.EXE");
     1172                            }
     1173                        }
     1174                        break;
     1175
     1176                        case PROG_VDM:              // DOS fullscreen
     1177                        case PROG_WINDOWEDVDM:      // DOS window
     1178                        {
     1179                            if (    (pszExtension = doshGetExtension(pDetails->pszExecutable))
     1180                                 && (!stricmp(pszExtension, "BAT"))
     1181                               )
     1182                            {
     1183                                CallBatchCorrectly(pDetails,
     1184                                                   pstrParamsPatched,
     1185                                                   NULL,
     1186                                                   "COMMAND.COM");
     1187                            }
     1188                        }
     1189                        break;
     1190                    } // end switch (pDetails->progt.progc)
     1191                }
     1192            }
     1193        }
     1194
     1195        if (!arc)
     1196        {
     1197            if (    (ulIsWinApp)
     1198                 && (    (pDetails->pszEnvironment == NULL)
     1199                      || (!strlen(pDetails->pszEnvironment))
     1200                    )
     1201               )
     1202            {
     1203                // this is a windoze app, and caller didn't bother
     1204                // to give us an environment:
     1205                // we MUST set one then, or we'll get the strangest
     1206                // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller]
     1207
     1208                DOSENVIRONMENT Env = {0};
     1209
     1210                // get standard WIN-OS/2 environment
     1211                PSZ pszTemp = appQueryDefaultWin31Environment();
     1212
     1213                if (!(arc = appParseEnvironment(pszTemp,
     1214                                                &Env)))
     1215                {
     1216                    // now override KBD_CTRL_BYPASS=CTRL_ESC
     1217                    if (    (!(arc = appSetEnvironmentVar(&Env,
     1218                                                          "KBD_CTRL_BYPASS=CTRL_ESC",
     1219                                                          FALSE)))        // add last
     1220                         && (!(arc = appConvertEnvironment(&Env,
     1221                                                           ppszWinOS2Env,   // freed at bottom
     1222                                                           NULL)))
     1223                       )
     1224                        pDetails->pszEnvironment = *ppszWinOS2Env;
     1225
     1226                    appFreeEnvironment(&Env);
     1227                }
     1228
     1229                free(pszTemp);
     1230            }
     1231
     1232            if (!arc)
     1233            {
     1234                if (!pDetails->pszTitle)
     1235                    pDetails->pszTitle = pDetails->pszExecutable;
     1236
     1237                // make sure params have a leading space
     1238                // V0.9.18 (2002-03-27) [umoeller]
     1239                if (pstrParamsPatched->ulLength)
     1240                {
     1241                    if (pstrParamsPatched->psz[0] != ' ')
     1242                    {
     1243                        XSTRING str2;
     1244                        xstrInit(&str2, 0);
     1245                        xstrcpy(&str2, " ", 1);
     1246                        xstrcats(&str2, pstrParamsPatched);
     1247                        xstrcpys(pstrParamsPatched, &str2);
     1248                        xstrClear(&str2);
     1249                                // we really need xstrInsert or something
     1250                    }
     1251                    pDetails->pszParameters = pstrParamsPatched->psz;
     1252                }
     1253                else
     1254                    pDetails->pszParameters = "";
     1255
     1256                if (!pDetails->pszIcon)
     1257                    pDetails->pszIcon = "";
     1258
     1259                if (!pDetails->pszStartupDir)
     1260                    pDetails->pszStartupDir = "";
     1261
     1262            }
     1263        }
     1264    }
     1265
     1266    return (arc);
     1267}
     1268
     1269/*
     1270 *@@ CallDosStartSession:
     1271 *
     1272 *@@added V0.9.18 (2002-03-27) [umoeller]
     1273 */
     1274
     1275static APIRET CallDosStartSession(HAPP *phapp,
     1276                                  const PROGDETAILS *pNewProgDetails, // in: program spec (req.)
     1277                                  ULONG cbFailingName,
     1278                                  PSZ pszFailingName)
     1279{
     1280    APIRET      arc = NO_ERROR;
     1281
     1282    BOOL        fCrit = FALSE,
     1283                fResetDir = FALSE;
     1284    CHAR        szCurrentDir[CCHMAXPATH];
     1285
     1286    ULONG       sid,
     1287                pid;
     1288    STARTDATA   SData;
     1289    SData.Length  = sizeof(STARTDATA);
     1290    SData.Related = SSF_RELATED_INDEPENDENT; // SSF_RELATED_CHILD;
     1291    // per default, try to start this in the foreground
     1292    SData.FgBg    = SSF_FGBG_FORE;
     1293    SData.TraceOpt = SSF_TRACEOPT_NONE;
     1294
     1295    SData.PgmTitle = pNewProgDetails->pszTitle;
     1296    SData.PgmName = pNewProgDetails->pszExecutable;
     1297    SData.PgmInputs = pNewProgDetails->pszParameters;
     1298
     1299    SData.TermQ = NULL;
     1300    SData.Environment = pNewProgDetails->pszEnvironment;
     1301    SData.InheritOpt = SSF_INHERTOPT_PARENT;    // ignored
     1302
     1303    switch (pNewProgDetails->progt.progc)
     1304    {
     1305        case PROG_FULLSCREEN:
     1306            SData.SessionType = SSF_TYPE_FULLSCREEN;
     1307        break;
     1308
     1309        case PROG_WINDOWABLEVIO:
     1310            SData.SessionType = SSF_TYPE_WINDOWABLEVIO;
     1311        break;
     1312
     1313        case PROG_PM:
     1314            SData.SessionType = SSF_TYPE_PM;
     1315            SData.FgBg = SSF_FGBG_BACK;     // otherwise we get ERROR_SMG_START_IN_BACKGROUND
     1316        break;
     1317
     1318        case PROG_VDM:
     1319            SData.SessionType = SSF_TYPE_VDM;
     1320        break;
     1321
     1322        case PROG_WINDOWEDVDM:
     1323            SData.SessionType = SSF_TYPE_WINDOWEDVDM;
     1324        break;
     1325
     1326        default:
     1327            SData.SessionType = SSF_TYPE_DEFAULT;
     1328    }
     1329
     1330    SData.IconFile = 0;
     1331    SData.PgmHandle = 0;
     1332
     1333    SData.PgmControl = 0;
     1334
     1335    if (pNewProgDetails->progt.fbVisible == SHE_VISIBLE)
     1336        SData.PgmControl |= SSF_CONTROL_VISIBLE;
     1337
     1338    if (pNewProgDetails->swpInitial.fl & SWP_HIDE)
     1339        SData.PgmControl |= SSF_CONTROL_INVISIBLE;
     1340
     1341    if (pNewProgDetails->swpInitial.fl & SWP_MAXIMIZE)
     1342        SData.PgmControl |= SSF_CONTROL_MAXIMIZE;
     1343    if (pNewProgDetails->swpInitial.fl & SWP_MINIMIZE)
     1344    {
     1345        SData.PgmControl |= SSF_CONTROL_MINIMIZE;
     1346        // use background then
     1347        SData.FgBg = SSF_FGBG_BACK;
     1348    }
     1349    if (pNewProgDetails->swpInitial.fl & SWP_MOVE)
     1350        SData.PgmControl |= SSF_CONTROL_SETPOS;
     1351    if (pNewProgDetails->swpInitial.fl & SWP_NOAUTOCLOSE)
     1352        SData.PgmControl |= SSF_CONTROL_NOAUTOCLOSE;
     1353
     1354    SData.InitXPos  = pNewProgDetails->swpInitial.x;
     1355    SData.InitYPos  = pNewProgDetails->swpInitial.y;
     1356    SData.InitXSize = pNewProgDetails->swpInitial.cx;
     1357    SData.InitYSize = pNewProgDetails->swpInitial.cy;
     1358
     1359    SData.Reserved = 0;
     1360    SData.ObjectBuffer  = pszFailingName;
     1361    SData.ObjectBuffLen = cbFailingName;
     1362
     1363    // now, if a required module cannot be found,
     1364    // DosStartSession still returns ERROR_FILE_NOT_FOUND
     1365    // (2), but pszFailingName will be set to something
     1366    // meaningful... so set it to a null string first
     1367    // and we can then check if it has changed
     1368    if (pszFailingName)
     1369        *pszFailingName = '\0';
     1370
     1371    TRY_QUIET(excpt1)
     1372    {
     1373        if (    (pNewProgDetails->pszStartupDir)
     1374             && (pNewProgDetails->pszStartupDir[0])
     1375           )
     1376        {
     1377            fCrit = !DosEnterCritSec();
     1378            if (    (!(arc = doshQueryCurrentDir(szCurrentDir)))
     1379                 && (!(arc = doshSetCurrentDir(pNewProgDetails->pszStartupDir)))
     1380               )
     1381                fResetDir = TRUE;
     1382        }
     1383
     1384        if (    (!arc)
     1385             && (!(arc = DosStartSession(&SData, &sid, &pid)))
     1386           )
     1387        {
     1388            // app started:
     1389            // compose HAPP from that
     1390            *phapp = sid;
     1391        }
     1392        else if (pszFailingName && *pszFailingName)
     1393            // DosStartSession has set this to something
     1394            // other than NULL: then use error code 1804,
     1395            // as cmd.exe does
     1396            arc = 1804;
     1397    }
     1398    CATCH(excpt1)
     1399    {
     1400        arc = ERROR_PROTECTION_VIOLATION;
     1401    } END_CATCH();
     1402
     1403    if (fResetDir)
     1404        doshSetCurrentDir(szCurrentDir);
     1405
     1406    if (fCrit)
     1407        DosExitCritSec();
     1408
     1409    #ifdef DEBUG_PROGRAMSTART
     1410        _Pmpf(("   DosStartSession returned %d, pszFailingName: \"%s\"",
     1411                  arc, pszFailingName));
     1412    #endif
     1413
     1414    return (arc);
     1415}
     1416
    8771417/*
    8781418 *@@ CallWinStartApp:
     
    8851425 *
    8861426 *@@added V0.9.18 (2002-02-13) [umoeller]
     1427 *@@changed V0.9.18 (2002-03-27) [umoeller]: made failing modules work
    8871428 */
    8881429
     
    8901431                              HWND hwndNotify,        // in: notify window or NULLHANDLE
    8911432                              const PROGDETAILS *pcProgDetails, // in: program spec (req.)
    892                               PCSZ pcszParamsPatched)
     1433                              ULONG cbFailingName,
     1434                              PSZ pszFailingName)
    8931435{
    8941436    ULONG   cb,
     
    9191461    if (cbTitle = strhSize(pcProgDetails->pszTitle))
    9201462        cb += cbTitle;
     1463    else
     1464        return (ERROR_INVALID_PARAMETER);
     1465    _Pmpf((__FUNCTION__ ": cbTitle is %d", cbTitle));
     1466
    9211467    if (cbExecutable = strhSize(pcProgDetails->pszExecutable))
    9221468        cb += cbExecutable;
     1469    else
     1470        return (ERROR_INVALID_PARAMETER);
     1471    _Pmpf(("    cbExecutable is %d", cbExecutable));
     1472
    9231473    if (cbParameters = strhSize(pcProgDetails->pszParameters))
    9241474        cb += cbParameters;
     1475    else
     1476        return (ERROR_INVALID_PARAMETER);
     1477    _Pmpf(("    cbParameters is %d", cbExecutable));
     1478
    9251479    if (cbStartupDir = strhSize(pcProgDetails->pszStartupDir))
    9261480        cb += cbStartupDir;
     1481    else
     1482        return (ERROR_INVALID_PARAMETER);
     1483    _Pmpf(("    cbStartupDir is %d", cbStartupDir));
     1484
    9271485    if (cbIcon = strhSize(pcProgDetails->pszIcon))
    9281486        cb += cbIcon;
     1487    else
     1488        return (ERROR_INVALID_PARAMETER);
     1489    _Pmpf(("    cbIcon is %d", cbIcon));
     1490
    9291491    if (cbEnvironment = appQueryEnvironmentLen(pcProgDetails->pszEnvironment))
    9301492        cb += cbEnvironment;
     1493    _Pmpf(("    cbEnvironment is %d", cbEnvironment));
     1494
     1495    _Pmpf(("    cbTotal is %d", cb));
    9311496
    9321497    if (cb > 60000)     // to be on the safe side
     
    9401505        {
    9411506            // alright, copy stuff
    942             PBYTE pThis;
    943 
    9441507            memset(pNewProgDetails, 0, sizeof(PROGDETAILS));
    9451508
    9461509            pNewProgDetails->Length = sizeof(PROGDETAILS);
    947             pNewProgDetails->progt.progc = pcProgDetails->progt.progc;
    948             pNewProgDetails->progt.fbVisible = pcProgDetails->progt.fbVisible;
    949             memcpy(&pNewProgDetails->swpInitial, &pcProgDetails->swpInitial, sizeof(SWP));
    950 
    951             pThis = (PBYTE)(pNewProgDetails + 1);
    952 
    953             if (cbTitle)
     1510
     1511            if (!(pNewProgDetails->progt.progc = pcProgDetails->progt.progc))
     1512                arc = ERROR_BAD_FORMAT;
     1513                        // this should never happen because we check
     1514                        // for this in appStartApp
     1515            else
    9541516            {
    955                 memcpy(pThis, pcProgDetails->pszTitle, cbTitle);
    956                 pNewProgDetails->pszTitle = pThis;
    957                 pThis += cbTitle;
    958             }
    959 
    960             if (cbExecutable)
    961             {
    962                 memcpy(pThis, pcProgDetails->pszExecutable, cbExecutable);
    963                 pNewProgDetails->pszExecutable = pThis;
    964                 pThis += cbExecutable;
    965             }
    966 
    967             if (cbParameters)
    968             {
    969                 memcpy(pThis, pcProgDetails->pszParameters, cbParameters);
    970                 pNewProgDetails->pszParameters = pThis;
    971                 pThis += cbParameters;
    972             }
    973 
    974             if (cbStartupDir)
    975             {
    976                 memcpy(pThis, pcProgDetails->pszStartupDir, cbStartupDir);
    977                 pNewProgDetails->pszStartupDir = pThis;
    978                 pThis += cbStartupDir;
    979             }
    980 
    981             if (cbIcon)
    982             {
    983                 memcpy(pThis, pcProgDetails->pszIcon, cbIcon);
    984                 pNewProgDetails->pszIcon = pThis;
    985                 pThis += cbIcon;
    986             }
    987 
    988             if (cbEnvironment)
    989             {
    990                 memcpy(pThis, pcProgDetails->pszEnvironment, cbEnvironment);
    991                 pNewProgDetails->pszEnvironment = pThis;
    992                 pThis += cbEnvironment;
    993             }
    994 
    995             #ifdef DEBUG_PROGRAMSTART
    996                 _Pmpf((__FUNCTION__ ": progt.progc: %d", pNewProgDetails->progt.progc));
    997                 _Pmpf(("    progt.fbVisible: 0x%lX", pNewProgDetails->progt.fbVisible));
    998                 _Pmpf(("    progt.pszTitle: \"%s\"", (pNewProgDetails->pszTitle) ? pNewProgDetails->pszTitle : "NULL"));
    999                 _Pmpf(("    exec: \"%s\"", (pNewProgDetails->pszExecutable) ? pNewProgDetails->pszExecutable : "NULL"));
    1000                 _Pmpf(("    params: \"%s\"", (pNewProgDetails->pszParameters) ? pNewProgDetails->pszParameters : "NULL"));
    1001                 _Pmpf(("    startup: \"%s\"", (pNewProgDetails->pszStartupDir) ? pNewProgDetails->pszStartupDir : "NULL"));
    1002                 _Pmpf(("    pszIcon: \"%s\"", (pNewProgDetails->pszIcon) ? pNewProgDetails->pszIcon : "NULL"));
    1003                 _Pmpf(("    environment: "));
     1517                PBYTE pThis;
     1518
     1519                pNewProgDetails->progt.fbVisible = pcProgDetails->progt.fbVisible;
     1520                memcpy(&pNewProgDetails->swpInitial, &pcProgDetails->swpInitial, sizeof(SWP));
     1521
     1522                // start copying into buffer right after PROGDETAILS
     1523                pThis = (PBYTE)(pNewProgDetails + 1);
     1524
     1525                #define COPY(id) if (cb ## id) { \
     1526                    memcpy(pThis, pcProgDetails->psz ## id, cb ## id); \
     1527                    pNewProgDetails->psz ## id = pThis; \
     1528                    pThis += cb ## id; }
     1529
     1530                COPY(Title);
     1531                COPY(Executable);
     1532                COPY(Parameters);
     1533                COPY(StartupDir);
     1534                COPY(Icon);
     1535                COPY(Environment);
     1536
     1537                #ifdef DEBUG_PROGRAMSTART
     1538                    _Pmpf((__FUNCTION__ ": progt.progc: %d", pNewProgDetails->progt.progc));
     1539                    _Pmpf(("    progt.fbVisible: 0x%lX", pNewProgDetails->progt.fbVisible));
     1540                    _Pmpf(("    progt.pszTitle: \"%s\"", (pNewProgDetails->pszTitle) ? pNewProgDetails->pszTitle : "NULL"));
     1541                    _Pmpf(("    exec: \"%s\"", (pNewProgDetails->pszExecutable) ? pNewProgDetails->pszExecutable : "NULL"));
     1542                    _Pmpf(("    params: \"%s\"", (pNewProgDetails->pszParameters) ? pNewProgDetails->pszParameters : "NULL"));
     1543                    _Pmpf(("    startup: \"%s\"", (pNewProgDetails->pszStartupDir) ? pNewProgDetails->pszStartupDir : "NULL"));
     1544                    _Pmpf(("    pszIcon: \"%s\"", (pNewProgDetails->pszIcon) ? pNewProgDetails->pszIcon : "NULL"));
     1545                    _Pmpf(("    environment: "));
     1546                    {
     1547                        PSZ pszThis = pNewProgDetails->pszEnvironment;
     1548                        while (pszThis && *pszThis)
     1549                        {
     1550                            _Pmpf(("      \"%s\"", pszThis));
     1551                            pszThis += strlen(pszThis) + 1;
     1552                        }
     1553                    }
     1554
     1555                    _Pmpf(("    swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
     1556                                pNewProgDetails->swpInitial.fl,
     1557                                pNewProgDetails->swpInitial.x,
     1558                                pNewProgDetails->swpInitial.y,
     1559                                pNewProgDetails->swpInitial.cx,
     1560                                pNewProgDetails->swpInitial.cy));
     1561                    _Pmpf(("    behind = %d, hwnd = %d, res1 = %d, res2 = %d",
     1562                                pNewProgDetails->swpInitial.hwndInsertBehind,
     1563                                pNewProgDetails->swpInitial.hwnd,
     1564                                pNewProgDetails->swpInitial.ulReserved1,
     1565                                pNewProgDetails->swpInitial.ulReserved2));
     1566
     1567                    /* DumpMemoryBlock((PBYTE)pNewProgDetails,
     1568                                    cb,
     1569                                    8); */
     1570
     1571                #endif
     1572
     1573                /* if (!(appIsWindowsApp(pNewProgDetails->progt.progc)))
     1574                    arc = CallDosStartSession(phapp,
     1575                                              pNewProgDetails,
     1576                                              cbFailingName,
     1577                                              pszFailingName);
     1578                else */
     1579                    // windoze app: use WinStartApp
     1580
     1581                if (!(*phapp = WinStartApp(hwndNotify,
     1582                                                    // receives WM_APPTERMINATENOTIFY
     1583                                           pNewProgDetails,
     1584                                           pNewProgDetails->pszParameters,
     1585                                           NULL,            // "reserved", PMREF says...
     1586                                           SAF_INSTALLEDCMDLINE)))
     1587                                                // we MUST use SAF_INSTALLEDCMDLINE
     1588                                                // or no Win-OS/2 session will start...
     1589                                                // whatever is going on here... Warp 4 FP11
     1590
     1591                                                // do not use SAF_STARTCHILDAPP, or the
     1592                                                // app will be terminated automatically
     1593                                                // when the WPS terminates!
    10041594                {
    1005                     PSZ pszThis = pNewProgDetails->pszEnvironment;
    1006                     while (pszThis && *pszThis)
     1595                    // cannot start app:
     1596                    PERRINFO pei;
     1597
     1598                    #ifdef DEBUG_PROGRAMSTART
     1599                        _Pmpf((__FUNCTION__ ": WinStartApp failed"));
     1600                    #endif
     1601
     1602                    // unfortunately WinStartApp doesn't
     1603                    // return meaningful codes like DosStartSession, so
     1604                    // try to see what happened
     1605
     1606                    if (pei = WinGetErrorInfo(0))
    10071607                    {
    1008                         _Pmpf(("      \"%s\"", pszThis));
    1009                         pszThis += strlen(pszThis) + 1;
     1608                        #ifdef DEBUG_PROGRAMSTART
     1609                            _Pmpf(("  WinGetErrorInfo returned 0x%lX, errorid 0x%lX, %d",
     1610                                        pei,
     1611                                        pei->idError,
     1612                                        ERRORIDERROR(pei->idError)));
     1613                        #endif
     1614
     1615                        switch (ERRORIDERROR(pei->idError))
     1616                        {
     1617                            case PMERR_DOS_ERROR: //  (0x1200)
     1618                            {
     1619                                /*
     1620                                PUSHORT pausMsgOfs = (PUSHORT)(((PBYTE)pei) + pei->offaoffszMsg);
     1621                                PULONG  pulData    = (PULONG)(((PBYTE)pei) + pei->offBinaryData);
     1622                                PSZ     pszMsg     = (PSZ)(((PBYTE)pei) + *pausMsgOfs);
     1623
     1624                                CHAR szMsg[1000];
     1625                                sprintf(szMsg, "cDetail: %d\nmsg: %s\n*pul: %d",
     1626                                        pei->cDetailLevel,
     1627                                        pszMsg,
     1628                                        *(pulData - 1));
     1629
     1630                                WinMessageBox(HWND_DESKTOP,
     1631                                              NULLHANDLE,
     1632                                              szMsg,
     1633                                              "Error",
     1634                                              0,
     1635                                              MB_OK | MB_MOVEABLE);
     1636
     1637                                // Very helpful. The message is "UNK 1200 E",
     1638                                // where I assume "UNK" means "unknown", which is
     1639                                // exactly what I was trying to find out. Oh my.
     1640                                // And cDetailLevel is always 1, which isn't terribly
     1641                                // helpful either. V0.9.18 (2002-03-27) [umoeller]
     1642                                // WHO THE &%õ$ CREATED THESE APIS?
     1643
     1644                                */
     1645
     1646                                // this is probably the case where the module
     1647                                // couldn't be loaded, so try DosStartSession
     1648                                // to get a meaningful return code... note that
     1649                                // this cannot handle hwndNotify then
     1650                                arc = CallDosStartSession(phapp,
     1651                                                          pNewProgDetails,
     1652                                                          cbFailingName,
     1653                                                          pszFailingName);
     1654                            }
     1655                            break;
     1656
     1657                            case PMERR_INVALID_APPL: //  (0x1530)
     1658                                    // Attempted to start an application whose type is not
     1659                                    // recognized by OS/2.
     1660                                    // This we get also if the executable doesn't exist...
     1661                                    // V0.9.18 (2002-03-27) [umoeller]
     1662                                // arc = ERROR_INVALID_EXE_SIGNATURE;
     1663                                arc = ERROR_FILE_NOT_FOUND;
     1664                            break;
     1665
     1666                            case PMERR_INVALID_PARAMETERS: //  (0x1208)
     1667                                    // An application parameter value is invalid for
     1668                                    // its converted PM type. For  example: a 4-byte
     1669                                    // value outside the range -32 768 to +32 767 cannot be
     1670                                    // converted to a SHORT, and a negative number cannot
     1671                                    // be converted to a ULONG or USHORT.
     1672                                arc = ERROR_INVALID_DATA;
     1673                            break;
     1674
     1675                            case PMERR_STARTED_IN_BACKGROUND: //  (0x1532)
     1676                                    // The application started a new session in the
     1677                                    // background.
     1678                                arc = ERROR_SMG_START_IN_BACKGROUND;
     1679                            break;
     1680
     1681                            case PMERR_INVALID_WINDOW: // (0x1206)
     1682                                    // The window specified with a Window List call
     1683                                    // is not a valid frame window.
     1684
     1685                            default:
     1686                                arc = ERROR_BAD_FORMAT;
     1687                            break;
     1688                        }
     1689
     1690                        WinFreeErrorInfo(pei);
    10101691                    }
    10111692                }
    1012 
    1013                 _Pmpf(("    swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
    1014                             pNewProgDetails->swpInitial.fl,
    1015                             pNewProgDetails->swpInitial.x,
    1016                             pNewProgDetails->swpInitial.y,
    1017                             pNewProgDetails->swpInitial.cx,
    1018                             pNewProgDetails->swpInitial.cy));
    1019                 _Pmpf(("    behind = %d, hwnd = %d, res1 = %d, res2 = %d",
    1020                             pNewProgDetails->swpInitial.hwndInsertBehind,
    1021                             pNewProgDetails->swpInitial.hwnd,
    1022                             pNewProgDetails->swpInitial.ulReserved1,
    1023                             pNewProgDetails->swpInitial.ulReserved2));
    1024             #endif
    1025 
    1026             if (!(*phapp = WinStartApp(hwndNotify,
    1027                                                 // receives WM_APPTERMINATENOTIFY
    1028                                        pNewProgDetails,
    1029                                        pNewProgDetails->pszParameters,
    1030                                        NULL,            // "reserved", PMREF says...
    1031                                        SAF_INSTALLEDCMDLINE)))
    1032                                             // we MUST use SAF_INSTALLEDCMDLINE
    1033                                             // or no Win-OS/2 session will start...
    1034                                             // whatever is going on here... Warp 4 FP11
    1035 
    1036                                             // do not use SAF_STARTCHILDAPP, or the
    1037                                             // app will be terminated automatically
    1038                                             // when the WPS terminates!
    1039             {
    1040                 // cannot start app:
    1041                 #ifdef DEBUG_PROGRAMSTART
    1042                     _Pmpf((__FUNCTION__ ": WinStartApp failed"));
    1043                 #endif
    1044 
    1045                 arc = ERROR_FILE_NOT_FOUND;
    1046                 // unfortunately WinStartApp doesn't
    1047                 // return meaningful codes like DosStartSession, so
    1048                 // try to see what happened
    1049                 /*
    1050                 switch (ERRORIDERROR(WinGetLastError(0)))
    1051                 {
    1052                     case PMERR_DOS_ERROR: //  (0x1200)
    1053                     {
    1054                         arc = ERROR_FILE_NOT_FOUND;
    1055 
    1056                         // this is probably the case where the module
    1057                         // couldn't be loaded, so try DosStartSession
    1058                         // to get a meaningful return code... note that
    1059                         // this cannot handle hwndNotify then
    1060                         RESULTCODES result;
    1061                         arc = DosExecPgm(pszFailingName,
    1062                                          cbFailingName,
    1063                                          EXEC_ASYNC,
    1064                                          NULL, // ProgDetails.pszParameters,
    1065                                          NULL, // ProgDetails.pszEnvironment,
    1066                                          &result,
    1067                                          ProgDetails.pszExecutable);
    1068                         ULONG sid, pid;
    1069                         STARTDATA   SData;
    1070                         SData.Length  = sizeof(STARTDATA);
    1071                         SData.Related = SSF_RELATED_CHILD; //INDEPENDENT;
    1072                         SData.FgBg    = SSF_FGBG_FORE;
    1073                         SData.TraceOpt = SSF_TRACEOPT_NONE;
    1074 
    1075                         SData.PgmTitle = ProgDetails.pszTitle;
    1076                         SData.PgmName = ProgDetails.pszExecutable;
    1077                         SData.PgmInputs = ProgDetails.pszParameters;
    1078 
    1079                         SData.TermQ = NULL;
    1080                         SData.Environment = ProgDetails.pszEnvironment;
    1081                         SData.InheritOpt = SSF_INHERTOPT_PARENT;    // ignored
    1082                         SData.SessionType = SSF_TYPE_DEFAULT;
    1083                         SData.IconFile = 0;
    1084                         SData.PgmHandle = 0;
    1085 
    1086                         SData.PgmControl = SSF_CONTROL_VISIBLE;
    1087 
    1088                         SData.InitXPos  = 30;
    1089                         SData.InitYPos  = 40;
    1090                         SData.InitXSize = 200;
    1091                         SData.InitYSize = 140;
    1092                         SData.Reserved = 0;
    1093                         SData.ObjectBuffer  = pszFailingName;
    1094                         SData.ObjectBuffLen = cbFailingName;
    1095 
    1096                         arc = DosStartSession(&SData, &sid, &pid);
    1097                     }
    1098                     break;
    1099 
    1100                     case PMERR_INVALID_APPL: //  (0x1530)
    1101                             // Attempted to start an application whose type is not
    1102                             // recognized by OS/2.
    1103                         arc = ERROR_INVALID_EXE_SIGNATURE;
    1104                     break;
    1105 
    1106                     case PMERR_INVALID_PARAMETERS: //  (0x1208)
    1107                             // An application parameter value is invalid for
    1108                             // its converted PM type. For  example: a 4-byte
    1109                             // value outside the range -32 768 to +32 767 cannot be
    1110                             // converted to a SHORT, and a negative number cannot
    1111                             // be converted to a ULONG or USHORT.
    1112                         arc = ERROR_INVALID_DATA;
    1113                     break;
    1114 
    1115                     case PMERR_STARTED_IN_BACKGROUND: //  (0x1532)
    1116                             // The application started a new session in the
    1117                             // background.
    1118                         arc = ERROR_SMG_START_IN_BACKGROUND;
    1119                     break;
    1120 
    1121                     case PMERR_INVALID_WINDOW: // (0x1206)
    1122                             // The window specified with a Window List call
    1123                             // is not a valid frame window.
    1124 
    1125                     default:
    1126                         arc = ERROR_BAD_FORMAT;
    1127                     break;
    1128                 }
    1129                 */
    11301693            }
    11311694
     
    12101773 *
    12111774 *      --  ERROR_INVALID_THREADID: not running on thread 1.
    1212  *          Since this uses WinStartApp internally and
    1213  *          WinStartApp completely hangs the session manager
    1214  *          if a Win-OS/2 full-screen session is started from
    1215  *          a thread that is NOT thread 1, this will now fail
    1216  *          with this error for safety (V0.9.16).
     1775 *          See remarks below.
    12171776 *
    12181777 *      --  ERROR_INVALID_PARAMETER: pcProgDetails or
     
    12251784 *
    12261785 *      --  ERROR_NOT_ENOUGH_MEMORY
     1786 *
     1787 *      <B>About enforcing thread 1</B>
     1788 *
     1789 *      OK, after long, long debugging hours, I have found
     1790 *      that WinStartApp hangs the system in the following
     1791 *      cases hard:
     1792 *
     1793 *      --  If a Win-OS/2 session is started and WinStartApp
     1794 *          is _not_ on thread 1. For this reason, we check
     1795 *          if the caller is trying to start a Win-OS/2
     1796 *          session and return ERROR_INVALID_THREADID if
     1797 *          this is not running on thread 1.
     1798 *
     1799 *      --  By contrast, WinStartApp hangs the system with
     1800 *          VIO sessions if we do the XWorkplace tricky of
     1801 *          redirecting WPProgram::wpOpen to thread 1
     1802 *          via WinPostMsg to the kernel thread-1 object
     1803 *          window. This also happens with DosStartSession,
     1804 *          so I suspect the bug is somewhere deeper in
     1805 *          SESMGR or wherever. So we no longer return
     1806 *          ERROR_INVALID_THREADID for non-Win-OS/2 sessions
     1807 *          (V0.9.18).
    12271808 *
    12281809 *@@added V0.9.6 (2000-10-16) [umoeller]
     
    12401821 *@@changed V0.9.16 (2002-01-04) [umoeller]: added more detailed error reports and *FailingName params
    12411822 *@@changed V0.9.18 (2002-02-13) [umoeller]: added CallWinStartApp to fix possible memory problems
     1823 *@@changed V0.9.18 (2002-03-27) [umoeller]: no longer returning ERROR_INVALID_THREADID, except for Win-OS/2 sessions
     1824 *@@changed V0.9.18 (2002-03-27) [umoeller]: extracted appFixProgDetails
    12421825 */
    12431826
    12441827APIRET appStartApp(HWND hwndNotify,        // in: notify window or NULLHANDLE
    12451828                   const PROGDETAILS *pcProgDetails, // in: program spec (req.)
    1246                    ULONG ulFlags,          // in: APP_RUN_* flags
     1829                   ULONG ulFlags,          // in: APP_RUN_* flags  or 0
    12471830                   HAPP *phapp,            // out: application handle if NO_ERROR is returned
    12481831                   ULONG cbFailingName,
    12491832                   PSZ pszFailingName)
    12501833{
    1251     APIRET          arc = NO_ERROR;
     1834    APIRET          arc;
    12521835    PROGDETAILS     ProgDetails;
     1836    XSTRING         strExecutablePatched,
     1837                    strParamsPatched;
     1838    PSZ             pszWinOS2Env = 0;
    12531839
    12541840    if (pszFailingName)
     
    12581844        return (ERROR_INVALID_PARAMETER);
    12591845
    1260     memcpy(&ProgDetails, pcProgDetails, sizeof(PROGDETAILS));
    1261             // pointers still point into old prog details buffer
    1262     ProgDetails.Length = sizeof(PROGDETAILS);
    1263     ProgDetails.progt.fbVisible = SHE_VISIBLE;
    1264 
    1265     // all this only makes sense if this contains something...
    1266     // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller]
    1267     if (    (!ProgDetails.pszExecutable)
    1268          || (!(*(ProgDetails.pszExecutable)))
    1269        )
    1270         arc = ERROR_INVALID_PARAMETER;
    1271     else if (doshMyTID() != 1)          // V0.9.16 (2001-10-19) [umoeller]
    1272         arc = ERROR_INVALID_THREADID;
    1273     else
    1274     {
    1275         ULONG           ulIsWinApp;
    1276 
    1277         CHAR            szFQExecutable[CCHMAXPATH];
    1278 
    1279         XSTRING         strParamsPatched;
    1280         PSZ             pszWinOS2Env = 0;
    1281 
    1282         // memset(&ProgDetails.swpInitial, 0, sizeof(SWP));
    1283         // this wasn't a good idea... WPProgram stores stuff
    1284         // in here, such as the "minimize on startup" -> SWP_MINIMIZE
    1285 
    1286         // duplicate parameters...
    1287         // we need this for string manipulations below...
    1288         if (ProgDetails.pszParameters)
    1289             xstrInitCopy(&strParamsPatched,
    1290                          ProgDetails.pszParameters,
    1291                          100);
     1846    xstrInit(&strExecutablePatched, 0);
     1847    xstrInit(&strParamsPatched, 0);
     1848
     1849    if (!(arc = appFixProgDetails(&ProgDetails,
     1850                                  pcProgDetails,
     1851                                  ulFlags,
     1852                                  &strExecutablePatched,
     1853                                  &strParamsPatched,
     1854                                  &pszWinOS2Env)))
     1855    {
     1856        if (pszFailingName)
     1857            strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);
     1858
     1859        if (    (appIsWindowsApp(ProgDetails.progt.progc))
     1860             && (doshMyTID() != 1)          // V0.9.16 (2001-10-19) [umoeller]
     1861           )
     1862            arc = ERROR_INVALID_THREADID;
    12921863        else
    1293             // no old params:
    1294             xstrInit(&strParamsPatched, 100);
    1295 
    1296         #ifdef DEBUG_PROGRAMSTART
    1297             _Pmpf((__FUNCTION__ ": old progc: 0x%lX", pcProgDetails->progt.progc));
    1298             _Pmpf(("  pszTitle: %s", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : NULL));
    1299             _Pmpf(("  pszIcon: %s", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : NULL));
    1300         #endif
    1301 
    1302         // program type fixups
    1303         switch (ProgDetails.progt.progc)        // that's a ULONG
    1304         {
    1305             case ((ULONG)-1):       // we get that sometimes...
    1306             case PROG_DEFAULT:
    1307             {
    1308                 // V0.9.12 (2001-05-26) [umoeller]
    1309                 ULONG ulDosAppType;
    1310                 appQueryAppType(ProgDetails.pszExecutable,
    1311                                 &ulDosAppType,
    1312                                 &ProgDetails.progt.progc);
    1313             }
    1314             break;
    1315         }
    1316 
    1317         // set session type from option flags
    1318         if (ulFlags & APP_RUN_FULLSCREEN)
    1319         {
    1320             if (ProgDetails.progt.progc == PROG_WINDOWABLEVIO)
    1321                 ProgDetails.progt.progc = PROG_FULLSCREEN;
    1322 
    1323             if (ProgDetails.progt.progc == PROG_WINDOWEDVDM)
    1324                 ProgDetails.progt.progc = PROG_VDM;
    1325         }
    1326 
    1327         if (ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc))
    1328         {
    1329             if (ulFlags & APP_RUN_FULLSCREEN)
    1330                 ProgDetails.progt.progc = (ulFlags & APP_RUN_ENHANCED)
    1331                                                 ? PROG_31_ENH
    1332                                                 : PROG_31_STD;
    1333             else
    1334             {
    1335                 if (ulFlags & APP_RUN_STANDARD)
    1336                     ProgDetails.progt.progc = (ulFlags & APP_RUN_SEPARATE)
    1337                                                 ? PROG_31_STDSEAMLESSVDM
    1338                                                 : PROG_31_STDSEAMLESSCOMMON;
    1339 
    1340                 if (ulFlags & APP_RUN_ENHANCED)
    1341                     ProgDetails.progt.progc = (ulFlags & APP_RUN_SEPARATE)
    1342                                                 ? PROG_31_ENHSEAMLESSVDM
    1343                                                 : PROG_31_ENHSEAMLESSCOMMON;
    1344             }
    1345 
    1346             // re-run V0.9.16 (2001-10-19) [umoeller]
    1347             ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc);
    1348         }
    1349 
    1350         /*
    1351          * command lines fixups:
    1352          *
    1353          */
    1354 
    1355         if (!strcmp(ProgDetails.pszExecutable, "*"))
    1356         {
    1357             /*
    1358              * "*" for command sessions:
    1359              *
    1360              */
    1361 
    1362             if (ulIsWinApp == 2)
    1363             {
    1364                 // enhanced Win-OS/2 session:
    1365                 PSZ psz = NULL;
    1366                 if (strParamsPatched.ulLength)
    1367                     // "/3 " + existing params
    1368                     psz = strdup(strParamsPatched.psz);
    1369 
    1370                 xstrcpy(&strParamsPatched, "/3 ", 0);
    1371 
    1372                 if (psz)
    1373                 {
    1374                     xstrcat(&strParamsPatched, psz, 0);
    1375                     free(psz);
    1376                 }
    1377             }
    1378 
    1379             if (ulIsWinApp)
    1380             {
    1381                 // cheat: WinStartApp doesn't support NULL
    1382                 // for Win-OS2 sessions, so manually start winos2.com
    1383                 ProgDetails.pszExecutable = "WINOS2.COM";
    1384                 // this is a DOS app, so fix this to DOS fullscreen
    1385                 ProgDetails.progt.progc = PROG_VDM;
    1386             }
    1387             else
    1388                 // for all other executable types
    1389                 // (including OS/2 and DOS sessions),
    1390                 // set pszExecutable to NULL; this will
    1391                 // have WinStartApp start a cmd shell
    1392                 ProgDetails.pszExecutable = NULL;
    1393 
    1394         } // end if (strcmp(pProgDetails->pszExecutable, "*") == 0)
    1395         else
    1396         {
    1397             // check if the executable is fully qualified; if so,
    1398             // check if the executable file exists
    1399             if (    (ProgDetails.pszExecutable[1] == ':')
    1400                  && (strchr(ProgDetails.pszExecutable, '\\'))
    1401                )
    1402             {
    1403                 ULONG ulAttr;
    1404                 if (!(arc = doshQueryPathAttr(ProgDetails.pszExecutable,
    1405                                               &ulAttr)))
    1406                 {
    1407                     // make sure startup dir is really a directory
    1408                     if (ProgDetails.pszStartupDir)
    1409                     {
    1410                         // it is valid to specify a startup dir of "C:"
    1411                         if (    (strlen(ProgDetails.pszStartupDir) > 2)
    1412                              && (!(arc = doshQueryPathAttr(ProgDetails.pszStartupDir,
    1413                                                            &ulAttr)))
    1414                              && (!(ulAttr & FILE_DIRECTORY))
    1415                            )
    1416                             arc = ERROR_PATH_NOT_FOUND;
    1417                     }
    1418                 }
    1419             }
    1420             else
    1421             {
    1422                 // _not_ fully qualified: look it up on the PATH then
    1423                 // V0.9.16 (2001-12-06) [umoeller]
    1424                 if (!(arc = doshSearchPath("PATH",
    1425                                            ProgDetails.pszExecutable,
    1426                                            szFQExecutable,
    1427                                            sizeof(szFQExecutable))))
    1428                     // alright, found it:
    1429                     ProgDetails.pszExecutable = szFQExecutable;
    1430             }
    1431 
    1432             if (!arc)
    1433             {
    1434                 PSZ pszExtension;
    1435                 switch (ProgDetails.progt.progc)
    1436                 {
    1437                     /*
    1438                      *  .CMD files fixups
    1439                      *
    1440                      */
    1441 
    1442                     case PROG_FULLSCREEN:       // OS/2 fullscreen
    1443                     case PROG_WINDOWABLEVIO:    // OS/2 window
    1444                     {
    1445                         if (    (pszExtension = doshGetExtension(ProgDetails.pszExecutable))
    1446                              && (!stricmp(pszExtension, "CMD"))
    1447                            )
    1448                         {
    1449                             CallBatchCorrectly(&ProgDetails,
    1450                                                &strParamsPatched,
    1451                                                "OS2_SHELL",
    1452                                                "CMD.EXE");
    1453                         }
    1454                     break; }
    1455 
    1456                     case PROG_VDM:              // DOS fullscreen
    1457                     case PROG_WINDOWEDVDM:      // DOS window
    1458                     {
    1459                         if (    (pszExtension = doshGetExtension(ProgDetails.pszExecutable))
    1460                              && (!stricmp(pszExtension, "BAT"))
    1461                            )
    1462                         {
    1463                             CallBatchCorrectly(&ProgDetails,
    1464                                                &strParamsPatched,
    1465                                                NULL,
    1466                                                "COMMAND.COM");
    1467                         }
    1468                     break; }
    1469                 } // end switch (ProgDetails.progt.progc)
    1470             }
    1471         }
    1472 
    1473         if (!arc)
    1474         {
    1475             if (    (ulIsWinApp)
    1476                  && (    (ProgDetails.pszEnvironment == NULL)
    1477                       || (!strlen(ProgDetails.pszEnvironment))
    1478                     )
    1479                )
    1480             {
    1481                 // this is a windoze app, and caller didn't bother
    1482                 // to give us an environment:
    1483                 // we MUST set one then, or we'll get the strangest
    1484                 // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller]
    1485 
    1486                 DOSENVIRONMENT Env = {0};
    1487 
    1488                 // get standard WIN-OS/2 environment
    1489                 PSZ pszTemp = appQueryDefaultWin31Environment();
    1490 
    1491                 if (!(arc = appParseEnvironment(pszTemp,
    1492                                                 &Env)))
    1493                 {
    1494                     // now override KBD_CTRL_BYPASS=CTRL_ESC
    1495                     if (    (!(arc = appSetEnvironmentVar(&Env,
    1496                                                           "KBD_CTRL_BYPASS=CTRL_ESC",
    1497                                                           FALSE)))        // add last
    1498                          && (!(arc = appConvertEnvironment(&Env,
    1499                                                            &pszWinOS2Env,   // freed at bottom
    1500                                                            NULL)))
    1501                        )
    1502                         ProgDetails.pszEnvironment = pszWinOS2Env;
    1503 
    1504                     appFreeEnvironment(&Env);
    1505                 }
    1506 
    1507                 free(pszTemp);
    1508             }
    1509 
    1510             if (!arc)
    1511             {
    1512                 if (!ProgDetails.pszTitle)
    1513                     ProgDetails.pszTitle = ProgDetails.pszExecutable;
    1514 
    1515                 ProgDetails.pszParameters = strParamsPatched.psz;
    1516 
    1517                 if (pszFailingName)
    1518                     strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);
    1519 
    1520                 arc = CallWinStartApp(phapp,
    1521                                       hwndNotify,
    1522                                       &ProgDetails,
    1523                                       strParamsPatched.psz);
    1524             }
    1525         }
    1526 
    1527         xstrClear(&strParamsPatched);
    1528         if (pszWinOS2Env)
    1529             free(pszWinOS2Env);
     1864            arc = CallWinStartApp(phapp,
     1865                                  hwndNotify,
     1866                                  &ProgDetails,
     1867                                  cbFailingName,
     1868                                  pszFailingName);
    15301869    } // end if (ProgDetails.pszExecutable)
     1870
     1871    xstrClear(&strParamsPatched);
     1872    xstrClear(&strExecutablePatched);
     1873
     1874    if (pszWinOS2Env)
     1875        free(pszWinOS2Env);
    15311876
    15321877    #ifdef DEBUG_PROGRAMSTART
     
    16181963    if (p = strrchr(pcszFile, '\\'))
    16191964    {
    1620        strhncpy0(szDir,
    1621                  pcszFile,
    1622                  p - pcszFile);
    1623        pd.pszStartupDir = szDir;
     1965        strhncpy0(szDir,
     1966                  pcszFile,
     1967                  p - pcszFile);
     1968        pd.pszStartupDir = szDir;
    16241969    }
    16251970
Note: See TracChangeset for help on using the changeset viewer.