Changeset 153 for trunk/src/helpers/apps.c
- Timestamp:
- Apr 14, 2002, 1:42:05 AM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/apps.c
r152 r153 49 49 #include "setup.h" // code generation and debugging options 50 50 51 #include "helpers\apps.h"52 51 #include "helpers\dosh.h" 53 52 #include "helpers\except.h" // exception handling … … 57 56 #include "helpers\winh.h" 58 57 #include "helpers\xstring.h" 58 59 #include "helpers\apps.h" 59 60 60 61 /* … … 843 844 * 844 845 *@@added V0.9.12 (2001-05-26) [umoeller] 845 */ 846 847 PSZ appQueryDefaultWin31Environment(VOID) 846 *@@changed V0.9.19 (2002-03-28) [umoeller]: now returning APIRET 847 */ 848 849 APIRET appQueryDefaultWin31Environment(PSZ *ppsz) 848 850 { 851 APIRET arc = NO_ERROR; 849 852 PSZ pszReturn = NULL; 850 853 ULONG ulSize = 0; 851 // get default environment (from Win-OS/2 settings object) 852 // from OS2.INI 853 PSZ pszDefEnv = prfhQueryProfileData(HINI_USER, 854 855 // get default environment (from Win-OS/2 settings object) from OS2.INI 856 PSZ pszDefEnv; 857 if (pszDefEnv = prfhQueryProfileData(HINI_USER, 854 858 "WINOS2", 855 859 "PM_GlobalWindows31Settings", 856 &ulSize); 857 if (pszDefEnv) 860 &ulSize)) 858 861 { 859 862 if (pszReturn = (PSZ)malloc(ulSize + 2)) … … 871 874 // okay.... now we got an OS/2-style environment 872 875 // with 0, 0, 00 strings 873 } 876 877 *ppsz = pszReturn; 878 } 879 else 880 arc = ERROR_NOT_ENOUGH_MEMORY; 874 881 875 882 free(pszDefEnv); 876 883 } 877 878 return (pszReturn); 884 else 885 arc = ERROR_BAD_ENVIRONMENT; 886 887 return (arc); 879 888 } 880 889 … … 957 966 958 967 /* 959 *@@ app FixProgDetails:968 *@@ appBuildProgDetails: 960 969 * extracted code from appStartApp to fix the 961 970 * given PROGDETAILS data to support the typical 962 * WPS stuff. 971 * WPS stuff and allocate a single block of 972 * shared memory containing all the data. 963 973 * 964 974 * This is now used by XWP's progOpenProgram … … 966 976 * session hangs. 967 977 * 968 * The caller is responsible for cleaning out 969 * the given three memory buffers. 978 * As input, this takes a PROGDETAILS structure, 979 * which is converted in various ways. In detail, 980 * this supports: 981 * 982 * -- starting "*" executables (command prompts 983 * for OS/2, DOS, Win-OS/2); 984 * 985 * -- starting ".CMD" and ".BAT" files as 986 * PROGDETAILS.pszExecutable; for those, we 987 * convert the executable and parameters to 988 * start CMD.EXE or COMMAND.COM with the "/C" 989 * parameter instead; 990 * 991 * -- starting apps which are not fully qualified 992 * and therefore assumed to be on the PATH 993 * (for which doshSearchPath("PATH") is called). 994 * 995 * Unless it is "*", PROGDETAILS.pszExecutable must 996 * be a proper file name. The full path may be omitted 997 * if it is on the PATH, but the extension (.EXE etc.) 998 * must be given. You can use doshFindExecutable to 999 * find executables if you don't know the extension. 1000 * 1001 * This also handles and merges special and default 1002 * environments for the app to be started. The 1003 * following should be respected: 1004 * 1005 * -- As with WinStartApp, if PROGDETAILS.pszEnvironment 1006 * is NULL, the new app inherits the default environment 1007 * from the shell. 1008 * 1009 * -- However, if you specify an environment, you _must_ 1010 * specify a complete environment. This function 1011 * will not merge environments. Use 1012 * appSetEnvironmentVar to change environment 1013 * variables in a complete environment set. 1014 * 1015 * -- If PROGDETAILS specifies a Win-OS/2 session 1016 * and PROGDETAILS.pszEnvironment is empty, 1017 * this uses the default Win-OS/2 environment 1018 * from OS2.INI. See appQueryDefaultWin31Environment. 1019 * 1020 * Even though this isn't clearly said in PMREF, 1021 * PROGDETAILS.swpInitial is important: 1022 * 1023 * -- To start a session minimized, set fl to SWP_MINIMIZE. 1024 * 1025 * -- To start a VIO session with auto-close disabled, 1026 * set the half-documented SWP_NOAUTOCLOSE flag (0x8000) 1027 * This flag is now in the newer toolkit headers. 1028 * 1029 * In addition, this supports the following session 1030 * flags with ulFlags if PROG_DEFAULT is specified: 1031 * 1032 * -- APP_RUN_FULLSCREEN: start a fullscreen session 1033 * for VIO, DOS, and Win-OS/2 programs. Otherwise 1034 * we start a windowed or (share) a seamless session. 1035 * Ignored if the program is PM. 1036 * 1037 * -- APP_RUN_ENHANCED: for Win-OS/2 sessions, use 1038 * enhanced mode. 1039 * Ignored if the program is not Win-OS/2. 1040 * 1041 * -- APP_RUN_STANDARD: for Win-OS/2 sessions, use 1042 * standard mode. 1043 * Ignored if the program is not Win-OS/2. 1044 * 1045 * -- APP_RUN_SEPARATE: for Win-OS/2 sessions, use 1046 * a separate session. 1047 * Ignored if the program is not Win-OS/2. 1048 * 1049 * If NO_ERROR is returned, *ppDetails receives a 1050 * new buffer of shared memory containing all the 1051 * data packed together. 1052 * 1053 * The shared memory is allocated unnamed and 1054 * with OBJ_GETTABLE. It is the responsibility 1055 * of the caller to call DosFreeMem on that buffer. 1056 * 1057 * Returns: 1058 * 1059 * -- NO_ERROR 1060 * 1061 * -- ERROR_INVALID_PARAMETER: pcProgDetails or 1062 * ppDetails is NULL; or PROGDETAILS.pszExecutable is NULL. 1063 * 1064 * -- ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND: 1065 * PROGDETAILS.pszExecutable and/or PROGDETAILS.pszStartupDir 1066 * are invalid. 1067 * A NULL PROGDETAILS.pszStartupDir is supported though. 1068 * 1069 * -- ERROR_BAD_FORMAT 1070 * 1071 * -- ERROR_BAD_ENVIRONMENT: environment is larger than 60.000 bytes. 1072 * 1073 * -- ERROR_NOT_ENOUGH_MEMORY 1074 * 1075 * plus the error codes from doshQueryPathAttr, doshSearchPath, 1076 * appParseEnvironment, appSetEnvironmentVar, and appConvertEnvironment. 970 1077 * 971 1078 *@@added V0.9.18 (2002-03-27) [umoeller] 972 */ 973 974 APIRET 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 1079 *@@changed V0.9.19 (2002-03-28) [umoeller]: now allocating contiguous buffer 1080 */ 1081 1082 APIRET appBuildProgDetails(PPROGDETAILS *ppDetails, // out: shared mem with fixed program spec (req.) 1083 const PROGDETAILS *pcProgDetails, // in: program spec (req.) 1084 ULONG ulFlags) // in: APP_RUN_* flags or 0 980 1085 { 981 1086 APIRET arc = NO_ERROR; 982 1087 983 memcpy(pDetails, pcProgDetails, sizeof(PROGDETAILS)); 1088 XSTRING strExecutablePatched, 1089 strParamsPatched; 1090 PSZ pszWinOS2Env = 0; 1091 1092 PROGDETAILS Details; 1093 1094 *ppDetails = NULL; 1095 1096 if (!pcProgDetails && !ppDetails) 1097 return (ERROR_INVALID_PARAMETER); 1098 1099 /* 1100 * part 1: 1101 * fix up the PROGDETAILS fields 1102 */ 1103 1104 xstrInit(&strExecutablePatched, 0); 1105 xstrInit(&strParamsPatched, 0); 1106 1107 memcpy(&Details, pcProgDetails, sizeof(PROGDETAILS)); 984 1108 // pointers still point into old prog details buffer 985 pDetails->Length = sizeof(PROGDETAILS);986 pDetails->progt.fbVisible = SHE_VISIBLE;1109 Details.Length = sizeof(PROGDETAILS); 1110 Details.progt.fbVisible = SHE_VISIBLE; 987 1111 988 1112 // all this only makes sense if this contains something... 989 1113 // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller] 990 if ( (! pDetails->pszExecutable)991 || (! (*(pDetails->pszExecutable)))1114 if ( (!Details.pszExecutable) 1115 || (!Details.pszExecutable[0]) 992 1116 ) 993 1117 arc = ERROR_INVALID_PARAMETER; … … 996 1120 ULONG ulIsWinApp; 997 1121 998 // memset(& pDetails->swpInitial, 0, sizeof(SWP));1122 // memset(&Details.swpInitial, 0, sizeof(SWP)); 999 1123 // this wasn't a good idea... WPProgram stores stuff 1000 1124 // in here, such as the "minimize on startup" -> SWP_MINIMIZE … … 1002 1126 // duplicate parameters... 1003 1127 // we need this for string manipulations below... 1004 if ( ( pDetails->pszParameters)1005 && ( *pDetails->pszParameters) // V0.9.181128 if ( (Details.pszParameters) 1129 && (Details.pszParameters[0]) // V0.9.18 1006 1130 ) 1007 xstrcpy( pstrParamsPatched,1008 pDetails->pszParameters,1131 xstrcpy(&strParamsPatched, 1132 Details.pszParameters, 1009 1133 0); 1010 1134 1011 1135 #ifdef DEBUG_PROGRAMSTART 1012 1136 _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));1137 _Pmpf((" pszTitle: %s", (Details.pszTitle) ? Details.pszTitle : NULL)); 1138 _Pmpf((" pszIcon: %s", (Details.pszIcon) ? Details.pszIcon : NULL)); 1015 1139 #endif 1016 1140 1017 1141 // program type fixups 1018 switch ( pDetails->progt.progc) // that's a ULONG1142 switch (Details.progt.progc) // that's a ULONG 1019 1143 { 1020 1144 case ((ULONG)-1): // we get that sometimes... … … 1023 1147 // V0.9.12 (2001-05-26) [umoeller] 1024 1148 ULONG ulDosAppType; 1025 appQueryAppType( pDetails->pszExecutable,1149 appQueryAppType(Details.pszExecutable, 1026 1150 &ulDosAppType, 1027 & pDetails->progt.progc);1151 &Details.progt.progc); 1028 1152 } 1029 1153 break; … … 1033 1157 if (ulFlags & APP_RUN_FULLSCREEN) 1034 1158 { 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))1159 if (Details.progt.progc == PROG_WINDOWABLEVIO) 1160 Details.progt.progc = PROG_FULLSCREEN; 1161 else if (Details.progt.progc == PROG_WINDOWEDVDM) 1162 Details.progt.progc = PROG_VDM; 1163 } 1164 1165 if (ulIsWinApp = appIsWindowsApp(Details.progt.progc)) 1042 1166 { 1043 1167 if (ulFlags & APP_RUN_FULLSCREEN) 1044 pDetails->progt.progc = (ulFlags & APP_RUN_ENHANCED)1168 Details.progt.progc = (ulFlags & APP_RUN_ENHANCED) 1045 1169 ? PROG_31_ENH 1046 1170 : PROG_31_STD; … … 1048 1172 { 1049 1173 if (ulFlags & APP_RUN_STANDARD) 1050 pDetails->progt.progc = (ulFlags & APP_RUN_SEPARATE)1174 Details.progt.progc = (ulFlags & APP_RUN_SEPARATE) 1051 1175 ? PROG_31_STDSEAMLESSVDM 1052 1176 : PROG_31_STDSEAMLESSCOMMON; 1053 1177 else if (ulFlags & APP_RUN_ENHANCED) 1054 pDetails->progt.progc = (ulFlags & APP_RUN_SEPARATE)1178 Details.progt.progc = (ulFlags & APP_RUN_SEPARATE) 1055 1179 ? PROG_31_ENHSEAMLESSVDM 1056 1180 : PROG_31_ENHSEAMLESSCOMMON; … … 1058 1182 1059 1183 // re-run V0.9.16 (2001-10-19) [umoeller] 1060 ulIsWinApp = appIsWindowsApp( pDetails->progt.progc);1184 ulIsWinApp = appIsWindowsApp(Details.progt.progc); 1061 1185 } 1062 1186 … … 1068 1192 */ 1069 1193 1070 if (!strcmp( pDetails->pszExecutable, "*"))1194 if (!strcmp(Details.pszExecutable, "*")) 1071 1195 { 1072 1196 /* … … 1079 1203 // enhanced Win-OS/2 session: 1080 1204 PSZ psz = NULL; 1081 if ( pstrParamsPatched->ulLength)1205 if (strParamsPatched.ulLength) 1082 1206 // "/3 " + existing params 1083 psz = strdup( pstrParamsPatched->psz);1084 1085 xstrcpy( pstrParamsPatched, "/3 ", 0);1207 psz = strdup(strParamsPatched.psz); 1208 1209 xstrcpy(&strParamsPatched, "/3 ", 0); 1086 1210 1087 1211 if (psz) 1088 1212 { 1089 xstrcat( pstrParamsPatched, psz, 0);1213 xstrcat(&strParamsPatched, psz, 0); 1090 1214 free(psz); 1091 1215 } … … 1096 1220 // cheat: WinStartApp doesn't support NULL 1097 1221 // for Win-OS2 sessions, so manually start winos2.com 1098 pDetails->pszExecutable = "WINOS2.COM";1222 Details.pszExecutable = "WINOS2.COM"; 1099 1223 // this is a DOS app, so fix this to DOS fullscreen 1100 pDetails->progt.progc = PROG_VDM;1224 Details.progt.progc = PROG_VDM; 1101 1225 } 1102 1226 else … … 1105 1229 // set pszExecutable to NULL; this will 1106 1230 // have WinStartApp start a cmd shell 1107 pDetails->pszExecutable = NULL;1231 Details.pszExecutable = NULL; 1108 1232 1109 1233 } // end if (strcmp(pProgDetails->pszExecutable, "*") == 0) … … 1112 1236 // check if the executable is fully qualified; if so, 1113 1237 // check if the executable file exists 1114 if ( ( pDetails->pszExecutable[1] == ':')1115 && (strchr( pDetails->pszExecutable, '\\'))1238 if ( (Details.pszExecutable[1] == ':') 1239 && (strchr(Details.pszExecutable, '\\')) 1116 1240 ) 1117 1241 { 1118 1242 ULONG ulAttr; 1119 if (!(arc = doshQueryPathAttr( pDetails->pszExecutable,1243 if (!(arc = doshQueryPathAttr(Details.pszExecutable, 1120 1244 &ulAttr))) 1121 1245 { 1122 1246 // make sure startup dir is really a directory 1123 if ( pDetails->pszStartupDir)1247 if (Details.pszStartupDir) 1124 1248 { 1125 1249 // it is valid to specify a startup dir of "C:" 1126 if ( (strlen( pDetails->pszStartupDir) > 2)1127 && (!(arc = doshQueryPathAttr( pDetails->pszStartupDir,1250 if ( (strlen(Details.pszStartupDir) > 2) 1251 && (!(arc = doshQueryPathAttr(Details.pszStartupDir, 1128 1252 &ulAttr))) 1129 1253 && (!(ulAttr & FILE_DIRECTORY)) … … 1139 1263 CHAR szFQExecutable[CCHMAXPATH]; 1140 1264 if (!(arc = doshSearchPath("PATH", 1141 pDetails->pszExecutable,1265 Details.pszExecutable, 1142 1266 szFQExecutable, 1143 1267 sizeof(szFQExecutable)))) 1144 1268 { 1145 1269 // alright, found it: 1146 xstrcpy( pstrExecutablePatched, szFQExecutable, 0);1147 pDetails->pszExecutable = pstrExecutablePatched->psz;1270 xstrcpy(&strExecutablePatched, szFQExecutable, 0); 1271 Details.pszExecutable = strExecutablePatched.psz; 1148 1272 } 1149 1273 } … … 1152 1276 { 1153 1277 PSZ pszExtension; 1154 switch ( pDetails->progt.progc)1278 switch (Details.progt.progc) 1155 1279 { 1156 1280 /* … … 1162 1286 case PROG_WINDOWABLEVIO: // OS/2 window 1163 1287 { 1164 if ( (pszExtension = doshGetExtension( pDetails->pszExecutable))1288 if ( (pszExtension = doshGetExtension(Details.pszExecutable)) 1165 1289 && (!stricmp(pszExtension, "CMD")) 1166 1290 ) 1167 1291 { 1168 CallBatchCorrectly( pDetails,1169 pstrParamsPatched,1292 CallBatchCorrectly(&Details, 1293 &strParamsPatched, 1170 1294 "OS2_SHELL", 1171 1295 "CMD.EXE"); … … 1177 1301 case PROG_WINDOWEDVDM: // DOS window 1178 1302 { 1179 if ( (pszExtension = doshGetExtension( pDetails->pszExecutable))1303 if ( (pszExtension = doshGetExtension(Details.pszExecutable)) 1180 1304 && (!stricmp(pszExtension, "BAT")) 1181 1305 ) 1182 1306 { 1183 CallBatchCorrectly( pDetails,1184 pstrParamsPatched,1307 CallBatchCorrectly(&Details, 1308 &strParamsPatched, 1185 1309 NULL, 1186 1310 "COMMAND.COM"); … … 1188 1312 } 1189 1313 break; 1190 } // end switch ( pDetails->progt.progc)1314 } // end switch (Details.progt.progc) 1191 1315 } 1192 1316 } … … 1196 1320 { 1197 1321 if ( (ulIsWinApp) 1198 && ( ( pDetails->pszEnvironment == NULL)1199 || (!strlen( pDetails->pszEnvironment))1322 && ( (Details.pszEnvironment == NULL) 1323 || (!strlen(Details.pszEnvironment)) 1200 1324 ) 1201 1325 ) … … 1209 1333 1210 1334 // get standard WIN-OS/2 environment 1211 PSZ pszTemp = appQueryDefaultWin31Environment(); 1212 1213 if (!(arc = appParseEnvironment(pszTemp, 1214 &Env))) 1335 PSZ pszTemp; 1336 if (!(arc = appQueryDefaultWin31Environment(&pszTemp))) 1215 1337 { 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); 1338 if (!(arc = appParseEnvironment(pszTemp, 1339 &Env))) 1340 { 1341 // now override KBD_CTRL_BYPASS=CTRL_ESC 1342 if ( (!(arc = appSetEnvironmentVar(&Env, 1343 "KBD_CTRL_BYPASS=CTRL_ESC", 1344 FALSE))) // add last 1345 && (!(arc = appConvertEnvironment(&Env, 1346 &pszWinOS2Env, // freed at bottom 1347 NULL))) 1348 ) 1349 Details.pszEnvironment = pszWinOS2Env; 1350 1351 appFreeEnvironment(&Env); 1352 } 1353 1354 free(pszTemp); 1227 1355 } 1228 1229 free(pszTemp);1230 1356 } 1231 1357 1232 1358 if (!arc) 1233 1359 { 1234 if (!pDetails->pszTitle) 1235 pDetails->pszTitle = pDetails->pszExecutable; 1360 // if no title is given, use the executable 1361 if (!Details.pszTitle) 1362 Details.pszTitle = Details.pszExecutable; 1236 1363 1237 1364 // make sure params have a leading space 1238 1365 // V0.9.18 (2002-03-27) [umoeller] 1239 if ( pstrParamsPatched->ulLength)1366 if (strParamsPatched.ulLength) 1240 1367 { 1241 if ( pstrParamsPatched->psz[0] != ' ')1368 if (strParamsPatched.psz[0] != ' ') 1242 1369 { 1243 1370 XSTRING str2; 1244 1371 xstrInit(&str2, 0); 1245 1372 xstrcpy(&str2, " ", 1); 1246 xstrcats(&str2, pstrParamsPatched);1247 xstrcpys( pstrParamsPatched, &str2);1373 xstrcats(&str2, &strParamsPatched); 1374 xstrcpys(&strParamsPatched, &str2); 1248 1375 xstrClear(&str2); 1249 1376 // we really need xstrInsert or something 1250 1377 } 1251 pDetails->pszParameters = pstrParamsPatched->psz;1378 Details.pszParameters = strParamsPatched.psz; 1252 1379 } 1253 1380 else 1254 pDetails->pszParameters = ""; 1255 1256 if (!pDetails->pszIcon) 1257 pDetails->pszIcon = ""; 1258 1259 if (!pDetails->pszStartupDir) 1260 pDetails->pszStartupDir = ""; 1381 // never pass null pointers 1382 Details.pszParameters = ""; 1383 1384 // never pass null pointers 1385 if (!Details.pszIcon) 1386 Details.pszIcon = ""; 1387 1388 // never pass null pointers 1389 if (!Details.pszStartupDir) 1390 Details.pszStartupDir = ""; 1261 1391 1262 1392 } 1263 1393 } 1264 1394 } 1395 1396 /* 1397 * part 2: 1398 * pack the fixed PROGDETAILS fields 1399 */ 1400 1401 if (!arc) 1402 { 1403 ULONG cb, 1404 cbTitle, 1405 cbExecutable, 1406 cbParameters, 1407 cbStartupDir, 1408 cbIcon, 1409 cbEnvironment; 1410 1411 // allocate a chunk of tiled memory from OS/2 to make sure 1412 // this is aligned on a 64K memory (backed up by a 16-bit 1413 // LDT selector); if it is not, and the environment 1414 // crosses segments, it gets truncated!! 1415 cb = sizeof(PROGDETAILS); 1416 if (cbTitle = strhSize(Details.pszTitle)) 1417 cb += cbTitle; 1418 1419 if (cbExecutable = strhSize(Details.pszExecutable)) 1420 cb += cbExecutable; 1421 1422 if (cbParameters = strhSize(Details.pszParameters)) 1423 cb += cbParameters; 1424 1425 if (cbStartupDir = strhSize(Details.pszStartupDir)) 1426 cb += cbStartupDir; 1427 1428 if (cbIcon = strhSize(Details.pszIcon)) 1429 cb += cbIcon; 1430 1431 if (cbEnvironment = appQueryEnvironmentLen(Details.pszEnvironment)) 1432 cb += cbEnvironment; 1433 1434 if (cb > 60000) // to be on the safe side 1435 arc = ERROR_BAD_ENVIRONMENT; // 10; 1436 else 1437 { 1438 PPROGDETAILS pNewProgDetails; 1439 // alright, allocate the shared memory now 1440 if (!(arc = DosAllocSharedMem((PVOID*)&pNewProgDetails, 1441 NULL, 1442 cb, 1443 PAG_COMMIT | OBJ_GETTABLE | OBJ_TILE | PAG_EXECUTE | PAG_READ | PAG_WRITE))) 1444 { 1445 // and copy stuff 1446 PBYTE pThis; 1447 1448 memset(pNewProgDetails, 0, cb); 1449 1450 pNewProgDetails->Length = sizeof(PROGDETAILS); 1451 1452 pNewProgDetails->progt.progc = Details.progt.progc; 1453 1454 pNewProgDetails->progt.fbVisible = Details.progt.fbVisible; 1455 memcpy(&pNewProgDetails->swpInitial, &Details.swpInitial, sizeof(SWP)); 1456 1457 // start copying into buffer right after PROGDETAILS 1458 pThis = (PBYTE)(pNewProgDetails + 1); 1459 1460 // handy macro to avoid typos 1461 #define COPY(id) if (cb ## id) { \ 1462 memcpy(pThis, Details.psz ## id, cb ## id); \ 1463 pNewProgDetails->psz ## id = pThis; \ 1464 pThis += cb ## id; } 1465 1466 COPY(Title); 1467 COPY(Executable); 1468 COPY(Parameters); 1469 COPY(StartupDir); 1470 COPY(Icon); 1471 COPY(Environment); 1472 1473 *ppDetails = pNewProgDetails; 1474 } 1475 } 1476 } 1477 1478 xstrClear(&strParamsPatched); 1479 xstrClear(&strExecutablePatched); 1480 1481 if (pszWinOS2Env) 1482 free(pszWinOS2Env); 1265 1483 1266 1484 return (arc); … … 1434 1652 PSZ pszFailingName) 1435 1653 { 1436 ULONG cb, 1437 cbTitle, 1438 cbExecutable, 1439 cbParameters, 1440 cbStartupDir, 1441 cbIcon, 1442 cbEnvironment; 1443 1444 APIRET arc = NO_ERROR; 1445 1446 /* 1447 if (WinMessageBox(HWND_DESKTOP, 1448 NULLHANDLE, 1449 (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL", 1450 "Start?", 1451 0, 1452 MB_YESNO | MB_MOVEABLE) 1453 != MBID_YES) 1454 return (ERROR_INTERRUPT); 1455 */ 1456 1457 // allocate a chunk of tiled memory from OS/2 to make sure 1458 // this is aligned on a 64K memory (backed up by a 16-bit 1459 // LDT selector) 1460 cb = sizeof(PROGDETAILS); 1461 if (cbTitle = strhSize(pcProgDetails->pszTitle)) 1462 cb += cbTitle; 1463 else 1654 APIRET arc = NO_ERROR; 1655 1656 if (!pcProgDetails) 1464 1657 return (ERROR_INVALID_PARAMETER); 1465 _Pmpf((__FUNCTION__ ": cbTitle is %d", cbTitle)); 1466 1467 if (cbExecutable = strhSize(pcProgDetails->pszExecutable)) 1468 cb += cbExecutable; 1469 else 1470 return (ERROR_INVALID_PARAMETER); 1471 _Pmpf((" cbExecutable is %d", cbExecutable)); 1472 1473 if (cbParameters = strhSize(pcProgDetails->pszParameters)) 1474 cb += cbParameters; 1475 else 1476 return (ERROR_INVALID_PARAMETER); 1477 _Pmpf((" cbParameters is %d", cbExecutable)); 1478 1479 if (cbStartupDir = strhSize(pcProgDetails->pszStartupDir)) 1480 cb += cbStartupDir; 1481 else 1482 return (ERROR_INVALID_PARAMETER); 1483 _Pmpf((" cbStartupDir is %d", cbStartupDir)); 1484 1485 if (cbIcon = strhSize(pcProgDetails->pszIcon)) 1486 cb += cbIcon; 1487 else 1488 return (ERROR_INVALID_PARAMETER); 1489 _Pmpf((" cbIcon is %d", cbIcon)); 1490 1491 if (cbEnvironment = appQueryEnvironmentLen(pcProgDetails->pszEnvironment)) 1492 cb += cbEnvironment; 1493 _Pmpf((" cbEnvironment is %d", cbEnvironment)); 1494 1495 _Pmpf((" cbTotal is %d", cb)); 1496 1497 if (cb > 60000) // to be on the safe side 1498 arc = ERROR_BAD_ENVIRONMENT; // 10; 1499 else 1500 { 1501 PPROGDETAILS pNewProgDetails; 1502 if (!(arc = DosAllocMem((PVOID*)&pNewProgDetails, 1503 cb, 1504 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE))) 1505 { 1506 // alright, copy stuff 1507 memset(pNewProgDetails, 0, sizeof(PROGDETAILS)); 1508 1509 pNewProgDetails->Length = sizeof(PROGDETAILS); 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 1658 1659 if (pszFailingName) 1660 *pszFailingName = '\0'; 1661 1662 if (!(*phapp = WinStartApp(hwndNotify, 1663 // receives WM_APPTERMINATENOTIFY 1664 (PPROGDETAILS)pcProgDetails, 1665 pcProgDetails->pszParameters, 1666 NULL, // "reserved", PMREF says... 1667 SAF_INSTALLEDCMDLINE))) 1668 // we MUST use SAF_INSTALLEDCMDLINE 1669 // or no Win-OS/2 session will start... 1670 // whatever is going on here... Warp 4 FP11 1671 1672 // do not use SAF_STARTCHILDAPP, or the 1673 // app will be terminated automatically 1674 // when the calling process terminates! 1675 { 1676 // cannot start app: 1677 PERRINFO pei; 1678 1679 #ifdef DEBUG_PROGRAMSTART 1680 _Pmpf((__FUNCTION__ ": WinStartApp failed")); 1681 #endif 1682 1683 // unfortunately WinStartApp doesn't 1684 // return meaningful codes like DosStartSession, so 1685 // try to see what happened 1686 1687 if (pei = WinGetErrorInfo(0)) 1688 { 1689 #ifdef DEBUG_PROGRAMSTART 1690 _Pmpf((" WinGetErrorInfo returned 0x%lX, errorid 0x%lX, %d", 1691 pei, 1692 pei->idError, 1693 ERRORIDERROR(pei->idError))); 1694 #endif 1695 1696 switch (ERRORIDERROR(pei->idError)) 1516 1697 { 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, 1698 case PMERR_DOS_ERROR: // (0x1200) 1699 { 1700 /* 1701 PUSHORT pausMsgOfs = (PUSHORT)(((PBYTE)pei) + pei->offaoffszMsg); 1702 PULONG pulData = (PULONG)(((PBYTE)pei) + pei->offBinaryData); 1703 PSZ pszMsg = (PSZ)(((PBYTE)pei) + *pausMsgOfs); 1704 1705 CHAR szMsg[1000]; 1706 sprintf(szMsg, "cDetail: %d\nmsg: %s\n*pul: %d", 1707 pei->cDetailLevel, 1708 pszMsg, 1709 *(pulData - 1)); 1710 1711 WinMessageBox(HWND_DESKTOP, 1712 NULLHANDLE, 1713 szMsg, 1714 "Error", 1715 0, 1716 MB_OK | MB_MOVEABLE); 1717 1718 // Very helpful. The message is "UNK 1200 E", 1719 // where I assume "UNK" means "unknown", which is 1720 // exactly what I was trying to find out. Oh my. 1721 // And cDetailLevel is always 1, which isn't terribly 1722 // helpful either. V0.9.18 (2002-03-27) [umoeller] 1723 // WHO THE &%õ$ CREATED THESE APIS? 1724 1725 */ 1726 1727 // this is probably the case where the module 1728 // couldn't be loaded, so try DosStartSession 1729 // to get a meaningful return code... note that 1730 // this cannot handle hwndNotify then 1731 /* arc = CallDosStartSession(phapp, 1732 pcProgDetails, 1576 1733 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! 1594 { 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)) 1607 { 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); 1691 } 1734 pszFailingName); */ 1735 arc = ERROR_FILE_NOT_FOUND; 1692 1736 } 1737 break; 1738 1739 case PMERR_INVALID_APPL: // (0x1530) 1740 // Attempted to start an application whose type is not 1741 // recognized by OS/2. 1742 // This we get also if the executable doesn't exist... 1743 // V0.9.18 (2002-03-27) [umoeller] 1744 // arc = ERROR_INVALID_EXE_SIGNATURE; 1745 arc = ERROR_FILE_NOT_FOUND; 1746 break; 1747 1748 case PMERR_INVALID_PARAMETERS: // (0x1208) 1749 // An application parameter value is invalid for 1750 // its converted PM type. For example: a 4-byte 1751 // value outside the range -32 768 to +32 767 cannot be 1752 // converted to a SHORT, and a negative number cannot 1753 // be converted to a ULONG or USHORT. 1754 arc = ERROR_INVALID_DATA; 1755 break; 1756 1757 case PMERR_STARTED_IN_BACKGROUND: // (0x1532) 1758 // The application started a new session in the 1759 // background. 1760 arc = ERROR_SMG_START_IN_BACKGROUND; 1761 break; 1762 1763 case PMERR_INVALID_WINDOW: // (0x1206) 1764 // The window specified with a Window List call 1765 // is not a valid frame window. 1766 1767 default: 1768 arc = ERROR_BAD_FORMAT; 1769 break; 1693 1770 } 1694 1771 1695 DosFreeMem(pNewProgDetails);1772 WinFreeErrorInfo(pei); 1696 1773 } 1697 1774 } … … 1706 1783 * work with all executable types. 1707 1784 * 1708 * This fixes the executable info to support: 1709 * 1710 * -- starting "*" executables (command prompts 1711 * for OS/2, DOS, Win-OS/2); 1712 * 1713 * -- starting ".CMD" and ".BAT" files as 1714 * PROGDETAILS.pszExecutable; 1715 * 1716 * -- starting apps which are not fully qualified 1717 * and therefore assumed to be on the PATH. 1718 * 1719 * Unless it is "*", PROGDETAILS.pszExecutable must 1720 * be a proper file name. The full path may be omitted 1721 * if it is on the PATH, but the extension (.EXE etc.) 1722 * must be given. You can use doshFindExecutable to 1723 * find executables if you don't know the extension. 1724 * 1725 * This also handles and merges special and default 1726 * environments for the app to be started. The 1727 * following should be respected: 1728 * 1729 * -- As with WinStartApp, if PROGDETAILS.pszEnvironment 1730 * is NULL, the new app inherits a default environment 1731 * from the shell. 1732 * 1733 * -- However, if you specify an environment, you _must_ 1734 * specify a complete environment. This function 1735 * will not merge environments. Use 1736 * appSetEnvironmentVar to change environment 1737 * variables in a complete environment set. 1738 * 1739 * -- If PROGDETAILS specifies a Win-OS/2 session 1740 * and PROGDETAILS.pszEnvironment is empty, 1741 * this uses the default Win-OS/2 environment. 1742 * See appQueryDefaultWin31Environment. 1743 * 1744 * Even though this isn't clearly said in PMREF, 1745 * PROGDETAILS.swpInitial is important: 1746 * 1747 * -- To start a session minimized, set SWP_MINIMIZE. 1748 * 1749 * -- To start a VIO session with auto-close disabled, 1750 * set the half-documented SWP_NOAUTOCLOSE flag (0x8000) 1751 * This flag is now in the newer toolkit headers. 1752 * 1753 * In addition, this supports the following session 1754 * flags with ulFlags if PROG_DEFAULT is specified: 1755 * 1756 * -- APP_RUN_FULLSCREEN 1757 * 1758 * -- APP_RUN_ENHANCED 1759 * 1760 * -- APP_RUN_STANDARD 1761 * 1762 * -- APP_RUN_SEPARATE 1785 * This first calls appBuildProgDetails (see 1786 * remarks there) and then calls WinStartApp. 1763 1787 * 1764 1788 * Since this calls WinStartApp in turn, this … … 1775 1799 * See remarks below. 1776 1800 * 1777 * -- ERROR_INVALID_PARAMETER: pcProgDetails or1778 * phapp is NULL; or PROGDETAILS.pszExecutable is NULL.1779 *1780 * -- ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND:1781 * PROGDETAILS.pszExecutable and/or PROGDETAILS.pszStartupDir1782 * are invalid.1783 * A NULL PROGDETAILS.pszStartupDir is supported though.1784 *1785 1801 * -- ERROR_NOT_ENOUGH_MEMORY 1802 * 1803 * plus the many error codes from appBuildProgDetails, 1804 * which gets called in turn. 1786 1805 * 1787 1806 * <B>About enforcing thread 1</B> … … 1797 1816 * this is not running on thread 1. 1798 1817 * 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). 1818 * -- By contrast, there are many situations where 1819 * calling WinStartApp from within the Workplace 1820 * process will hang the system, most notably 1821 * with VIO sessions. I have been unable to figure 1822 * out why this happens, so XWorkplace now uses 1823 * its daemon to call WinStartApp instead. 1824 * 1825 * As a word of wisdom, do not call this from 1826 * within the Workplace process. For some strange 1827 * reason though, the XWorkplace "Run" dialog 1828 * (which uses this) _does_ work. Whatever. 1808 1829 * 1809 1830 *@@added V0.9.6 (2000-10-16) [umoeller] … … 1822 1843 *@@changed V0.9.18 (2002-02-13) [umoeller]: added CallWinStartApp to fix possible memory problems 1823 1844 *@@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 1845 *@@changed V0.9.18 (2002-03-27) [umoeller]: extracted appBuildProgDetails 1846 *@@changed V0.9.19 (2002-03-28) [umoeller]: adjusted for new appBuildProgDetails 1825 1847 */ 1826 1848 … … 1833 1855 { 1834 1856 APIRET arc; 1835 PROGDETAILS ProgDetails; 1836 XSTRING strExecutablePatched, 1837 strParamsPatched; 1838 PSZ pszWinOS2Env = 0; 1839 1840 if (pszFailingName) 1841 *pszFailingName = '\0'; 1842 1843 if (!pcProgDetails || !phapp) 1857 1858 PPROGDETAILS pDetails; 1859 1860 if (!phapp) 1844 1861 return (ERROR_INVALID_PARAMETER); 1845 1862 1846 xstrInit(&strExecutablePatched, 0); 1847 xstrInit(&strParamsPatched, 0); 1848 1849 if (!(arc = appFixProgDetails(&ProgDetails, 1850 pcProgDetails, 1851 ulFlags, 1852 &strExecutablePatched, 1853 &strParamsPatched, 1854 &pszWinOS2Env))) 1863 if (!(arc = appBuildProgDetails(&pDetails, 1864 pcProgDetails, 1865 ulFlags))) 1855 1866 { 1856 1867 if (pszFailingName) 1857 strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);1858 1859 if ( (appIsWindowsApp( ProgDetails.progt.progc))1868 strhncpy0(pszFailingName, pDetails->pszExecutable, cbFailingName); 1869 1870 if ( (appIsWindowsApp(pDetails->progt.progc)) 1860 1871 && (doshMyTID() != 1) // V0.9.16 (2001-10-19) [umoeller] 1861 1872 ) … … 1864 1875 arc = CallWinStartApp(phapp, 1865 1876 hwndNotify, 1866 &ProgDetails,1877 pDetails, 1867 1878 cbFailingName, 1868 1879 pszFailingName); 1880 1881 DosFreeMem(pDetails); 1882 1869 1883 } // end if (ProgDetails.pszExecutable) 1870 1871 xstrClear(&strParamsPatched);1872 xstrClear(&strExecutablePatched);1873 1874 if (pszWinOS2Env)1875 free(pszWinOS2Env);1876 1884 1877 1885 #ifdef DEBUG_PROGRAMSTART
Note:
See TracChangeset
for help on using the changeset viewer.