Changeset 113 for trunk/src/helpers/apps.c
- Timestamp:
- Oct 23, 2001, 11:25:46 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/apps.c
r108 r113 47 47 #include "helpers\prfh.h" 48 48 #include "helpers\stringh.h" 49 #include "helpers\winh.h" 49 50 #include "helpers\xstring.h" 50 51 … … 797 798 * from the shell. 798 799 * 799 +-- However, if you specify an environment, you _must_800 * specify a comple mete environment. This function800 * -- However, if you specify an environment, you _must_ 801 * specify a complete environment. This function 801 802 * will not merge environments. Use 802 803 * appSetEnvironmentVar to change environment … … 808 809 * See appQueryDefaultWin31Environment. 809 810 * 810 * -- WARNING: Since this uses WinStartApp internally,811 * and WinStartApp completely hangs PM if a Win-OS/2812 * full-screen session is started from a thread that813 * is NOT thread1, THIS SHOULD ONLY BE CALLED ON814 * THREAD 1 of your application.815 *816 811 * Even though this isn't clearly said in PMREF, 817 812 * PROGDETAILS.swpInitial is important: … … 823 818 * This flag is now in the newer toolkit headers. 824 819 * 820 * In addition, this supports the following session 821 * flags with ulFlags if PROG_DEFAULT is specified: 822 * 823 * -- APP_RUN_FULLSCREEN 824 * 825 * -- APP_RUN_ENHANCED 826 * 827 * -- APP_RUN_STANDARD 828 * 829 * -- APP_RUN_SEPARATE 830 * 825 831 * Since this calls WinStartApp in turn, this 826 832 * requires a message queue on the calling thread. 833 * 834 * Note that this also does minimal checking on 835 * the specified parameters so it can return something 836 * more meaningful than FALSE like WinStartApp. 837 * As a result, you get a DOS error code now (V0.9.16). 838 * 839 * Most importantly: 840 * 841 * -- ERROR_INVALID_THREADID: not running on thread 1. 842 * Since this uses WinStartApp internally and 843 * WinStartApp completely hangs the session manager 844 * if a Win-OS/2 full-screen session is started from 845 * a thread that is NOT thread1, this will fail 846 * with an error for safety (V0.9.16). 847 * 848 * -- ERROR_INVALID_PARAMETER: pcProgDetails or 849 * phapp is NULL; or PROGDETAILS.pszExecutable is NULL. 850 * 851 * -- ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND: 852 * PROGDETAILS.pszExecutable and/or PROGDETAILS.pszStartupDir 853 * are invalid. 854 * A NULL PROGDETAILS.pszStartupDir is supported though. 855 * 856 * -- ERROR_NOT_ENOUGH_MEMORY 827 857 * 828 858 *@@added V0.9.6 (2000-10-16) [umoeller] … … 834 864 *@@changed V0.9.14 (2001-08-07) [pr]: removed some env. strings for Win. apps. 835 865 *@@changed V0.9.14 (2001-08-23) [pr]: added session type options 836 */ 837 838 HAPP appStartApp(HWND hwndNotify, // in: notify window (as with WinStartApp) 839 const PROGDETAILS *pcProgDetails, // in: program data 840 ULONG ulFlags) // in: session type options 841 { 842 HAPP happ = NULLHANDLE; 843 XSTRING strParamsPatched; 866 *@@changed V0.9.16 (2001-10-19) [umoeller]: added prototype to return APIRET 867 *@@changed V0.9.16 (2001-10-19) [umoeller]: added thread-1 check 868 */ 869 870 APIRET appStartApp(HWND hwndNotify, // in: notify window or NULLHANDLE 871 const PROGDETAILS *pcProgDetails, // in: program spec (req.) 872 ULONG ulFlags, // in: APP_RUN_* flags 873 HAPP *phapp) // out: application handle if NO_ERROR is returned 874 { 875 APIRET arc = NO_ERROR; 844 876 PROGDETAILS ProgDetails; 845 877 846 PSZ pszWinOS2Env = 0; 878 if (!pcProgDetails || !phapp) 879 return (ERROR_INVALID_PARAMETER); 847 880 848 881 memcpy(&ProgDetails, pcProgDetails, sizeof(PROGDETAILS)); … … 850 883 ProgDetails.Length = sizeof(PROGDETAILS); 851 884 ProgDetails.progt.fbVisible = SHE_VISIBLE; 852 // ProgDetails.pszEnvironment = 0;853 885 854 886 // all this only makes sense if this contains something... 855 887 // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller] 856 if (ProgDetails.pszExecutable) 857 { 858 ULONG ulIsWinApp; 888 if (!ProgDetails.pszExecutable) 889 arc = ERROR_INVALID_PARAMETER; 890 else if (doshMyTID() != 1) // V0.9.16 (2001-10-19) [umoeller] 891 arc = ERROR_INVALID_THREADID; 892 else 893 { 894 ULONG ulIsWinApp; 895 896 XSTRING strParamsPatched; 897 PSZ pszWinOS2Env = 0; 859 898 860 899 // memset(&ProgDetails.swpInitial, 0, sizeof(SWP)); … … 891 930 } 892 931 893 // Set session type from option flags932 // set session type from option flags 894 933 if (ulFlags & APP_RUN_FULLSCREEN) 895 934 { … … 919 958 : PROG_31_ENHSEAMLESSCOMMON; 920 959 } 960 961 // re-run V0.9.16 (2001-10-19) [umoeller] 962 ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc); 921 963 } 922 964 … … 968 1010 else 969 1011 { 970 PSZ pszExtension; 971 switch (ProgDetails.progt.progc) 972 { 973 /* 974 * .CMD files fixups 975 * 976 */ 977 978 case PROG_FULLSCREEN: // OS/2 fullscreen 979 case PROG_WINDOWABLEVIO: // OS/2 window 1012 // now check if the executable is valid 1013 // V0.9.16 (2001-10-19) [umoeller] 1014 ULONG ulAttr; 1015 _Pmpf((" %d now, checking %s", arc, ProgDetails.pszExecutable)); 1016 if (!(arc = doshQueryPathAttr(ProgDetails.pszExecutable, 1017 &ulAttr))) 1018 { 1019 // make sure startup dir is really a directory 1020 if (ProgDetails.pszStartupDir) 980 1021 { 981 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable)) 982 && (!stricmp(pszExtension, "CMD")) 1022 _Pmpf((" checking %s", ProgDetails.pszStartupDir)); 1023 if (!(arc = doshQueryPathAttr(ProgDetails.pszStartupDir, 1024 &ulAttr))) 1025 if (!(ulAttr & FILE_DIRECTORY)) 1026 arc = ERROR_PATH_NOT_FOUND; 1027 // @@todo 1028 } 1029 } 1030 1031 _Pmpf((" after checking %d", arc)); 1032 1033 if (!arc) 1034 { 1035 PSZ pszExtension; 1036 switch (ProgDetails.progt.progc) 1037 { 1038 /* 1039 * .CMD files fixups 1040 * 1041 */ 1042 1043 case PROG_FULLSCREEN: // OS/2 fullscreen 1044 case PROG_WINDOWABLEVIO: // OS/2 window 1045 { 1046 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable)) 1047 && (!stricmp(pszExtension, "CMD")) 1048 ) 1049 { 1050 CallBatchCorrectly(&ProgDetails, 1051 &strParamsPatched, 1052 "OS2_SHELL", 1053 "CMD.EXE"); 1054 } 1055 break; } 1056 1057 case PROG_VDM: // DOS fullscreen 1058 case PROG_WINDOWEDVDM: // DOS window 1059 { 1060 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable)) 1061 && (!stricmp(pszExtension, "BAT")) 1062 ) 1063 { 1064 CallBatchCorrectly(&ProgDetails, 1065 &strParamsPatched, 1066 NULL, 1067 "COMMAND.COM"); 1068 } 1069 break; } 1070 } // end switch (ProgDetails.progt.progc) 1071 } 1072 } 1073 1074 if (!arc) 1075 { 1076 if ( (ulIsWinApp) 1077 && ( (ProgDetails.pszEnvironment == NULL) 1078 || (!strlen(ProgDetails.pszEnvironment)) 1079 ) 1080 ) 1081 { 1082 // this is a windoze app, and caller didn't bother 1083 // to give us an environment: 1084 // we MUST set one then, or we'll get the strangest 1085 // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller] 1086 1087 DOSENVIRONMENT Env = {0}; 1088 1089 // get standard WIN-OS/2 environment 1090 PSZ pszTemp = appQueryDefaultWin31Environment(); 1091 1092 if (!(arc = appParseEnvironment(pszTemp, 1093 &Env))) 1094 { 1095 // now override KBD_CTRL_BYPASS=CTRL_ESC 1096 if ( (!(arc = appSetEnvironmentVar(&Env, 1097 "KBD_CTRL_BYPASS=CTRL_ESC", 1098 FALSE))) // add last 1099 && (!(arc = appConvertEnvironment(&Env, 1100 &pszWinOS2Env, // freed at bottom 1101 NULL))) 983 1102 ) 1103 ProgDetails.pszEnvironment = pszWinOS2Env; 1104 1105 appFreeEnvironment(&Env); 1106 } 1107 1108 free(pszTemp); 1109 } 1110 1111 if (!arc) 1112 { 1113 if (!ProgDetails.pszTitle) 1114 ProgDetails.pszTitle = ProgDetails.pszExecutable; 1115 1116 ProgDetails.pszParameters = strParamsPatched.psz; 1117 1118 /* _Pmpf(("progt.progc: %d", ProgDetails.progt.progc)); 1119 _Pmpf(("progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible)); 1120 _Pmpf(("progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL")); 1121 _Pmpf(("exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL")); 1122 _Pmpf(("params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL")); 1123 _Pmpf(("startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL")); 1124 _Pmpf(("pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL")); 1125 _Pmpf(("environment: ")); 1126 { 1127 PSZ pszThis = ProgDetails.pszEnvironment; 1128 while (pszThis && *pszThis) 984 1129 { 985 CallBatchCorrectly(&ProgDetails, 986 &strParamsPatched, 987 "OS2_SHELL", 988 "CMD.EXE"); 1130 _Pmpf((" \"%s\"", pszThis)); 1131 pszThis += strlen(pszThis) + 1; 989 1132 } 990 break; } 991 992 case PROG_VDM: // DOS fullscreen 993 case PROG_WINDOWEDVDM: // DOS window 994 { 995 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable)) 996 && (!stricmp(pszExtension, "BAT")) 997 ) 998 { 999 CallBatchCorrectly(&ProgDetails, 1000 &strParamsPatched, 1001 NULL, 1002 "COMMAND.COM"); 1003 } 1004 break; } 1005 } // end switch (ProgDetails.progt.progc) 1006 } 1007 1008 if ( (ulIsWinApp) 1009 && ( (ProgDetails.pszEnvironment == NULL) 1010 || (!strlen(ProgDetails.pszEnvironment)) 1011 ) 1012 ) 1013 { 1014 // this is a windoze app, and caller didn't bother 1015 // to give us an environment: 1016 // we MUST set one then, or we'll get the strangest 1017 // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller] 1018 1019 DOSENVIRONMENT Env = {0}; 1020 1021 // get standard WIN-OS/2 environment 1022 PSZ pszTemp = appQueryDefaultWin31Environment(); 1023 1024 if (!appParseEnvironment(pszTemp, 1025 &Env)) 1026 { 1027 // now override KBD_CTRL_BYPASS=CTRL_ESC 1028 appSetEnvironmentVar(&Env, 1029 "KBD_CTRL_BYPASS=CTRL_ESC", 1030 FALSE); // add last 1031 /* 1032 * These should be set by the default environment. It is 1033 * not our business to override them really. V0.9.14 1034 * 1035 appSetEnvironmentVar(&Env, 1036 "KBD_ALTHOME_BYPASS=1", 1037 FALSE); // add last 1038 appSetEnvironmentVar(&Env, 1039 "INT_DURING_IO=1", 1040 FALSE); // add last 1041 appSetEnvironmentVar(&Env, 1042 "HW_TIMER=1", 1043 FALSE); // add last 1044 appSetEnvironmentVar(&Env, 1045 "MOUSE_EXCLUSIVE_ACCESS=0", 1046 FALSE); // add last 1047 appSetEnvironmentVar(&Env, 1048 "VIDEO_RETRACE_EMULATION=1", 1049 FALSE); // add last 1050 appSetEnvironmentVar(&Env, 1051 "VIDEO_SWITCH_NOTIFICATION=1", 1052 FALSE); // add last 1053 appSetEnvironmentVar(&Env, 1054 "VIDEO_8514A_XGA_IOTRAP=0", 1055 FALSE); // add last 1056 */ 1057 1058 if (!appConvertEnvironment(&Env, 1059 &pszWinOS2Env, // freed at bottom 1060 NULL)) 1061 ProgDetails.pszEnvironment = pszWinOS2Env; 1062 1063 appFreeEnvironment(&Env); 1064 } 1065 1066 free(pszTemp); 1067 } 1068 1069 if (!ProgDetails.pszTitle) 1070 ProgDetails.pszTitle = ProgDetails.pszExecutable; 1071 1072 ProgDetails.pszParameters = strParamsPatched.psz; 1073 1074 /* _Pmpf(("progt.progc: %d", ProgDetails.progt.progc)); 1075 _Pmpf(("progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible)); 1076 _Pmpf(("progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL")); 1077 _Pmpf(("exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL")); 1078 _Pmpf(("params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL")); 1079 _Pmpf(("startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL")); 1080 _Pmpf(("pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL")); 1081 _Pmpf(("environment: ")); 1082 { 1083 PSZ pszThis = ProgDetails.pszEnvironment; 1084 while (pszThis && *pszThis) 1085 { 1086 _Pmpf((" \"%s\"", pszThis)); 1087 pszThis += strlen(pszThis) + 1; 1088 } 1089 } 1090 1091 _Pmpf(("swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:", 1092 ProgDetails.swpInitial.fl, 1093 ProgDetails.swpInitial.x, 1094 ProgDetails.swpInitial.y, 1095 ProgDetails.swpInitial.cx, 1096 ProgDetails.swpInitial.cy)); 1097 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d", 1098 ProgDetails.swpInitial.hwndInsertBehind, 1099 ProgDetails.swpInitial.hwnd, 1100 ProgDetails.swpInitial.ulReserved1, 1101 ProgDetails.swpInitial.ulReserved2)); 1102 */ 1103 1104 /* if (WinMessageBox(HWND_DESKTOP, 1105 NULLHANDLE, 1106 (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL", 1107 "Start?", 1108 0, 1109 MB_YESNO | MB_MOVEABLE) 1110 == MBID_YES) */ 1111 happ = WinStartApp(hwndNotify, 1112 // receives WM_APPTERMINATENOTIFY 1113 &ProgDetails, 1114 strParamsPatched.psz, 1115 NULL, // "reserved", PMREF says... 1116 SAF_INSTALLEDCMDLINE); 1117 // we MUST use SAF_INSTALLEDCMDLINE 1118 // or no Win-OS/2 session will start... 1119 // whatever is going on here... Warp 4 FP11 1120 1121 // do not use SAF_STARTCHILDAPP, or the 1122 // app will be terminated automatically 1123 // when the WPS terminates! 1124 1125 // _Pmpf((__FUNCTION__ ": got happ 0x%lX", happ)); 1133 } 1134 1135 _Pmpf(("swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:", 1136 ProgDetails.swpInitial.fl, 1137 ProgDetails.swpInitial.x, 1138 ProgDetails.swpInitial.y, 1139 ProgDetails.swpInitial.cx, 1140 ProgDetails.swpInitial.cy)); 1141 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d", 1142 ProgDetails.swpInitial.hwndInsertBehind, 1143 ProgDetails.swpInitial.hwnd, 1144 ProgDetails.swpInitial.ulReserved1, 1145 ProgDetails.swpInitial.ulReserved2)); 1146 */ 1147 1148 /* if (WinMessageBox(HWND_DESKTOP, 1149 NULLHANDLE, 1150 (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL", 1151 "Start?", 1152 0, 1153 MB_YESNO | MB_MOVEABLE) 1154 == MBID_YES) */ 1155 if (!(*phapp = WinStartApp(hwndNotify, 1156 // receives WM_APPTERMINATENOTIFY 1157 &ProgDetails, 1158 strParamsPatched.psz, 1159 NULL, // "reserved", PMREF says... 1160 SAF_INSTALLEDCMDLINE))) 1161 // we MUST use SAF_INSTALLEDCMDLINE 1162 // or no Win-OS/2 session will start... 1163 // whatever is going on here... Warp 4 FP11 1164 1165 // do not use SAF_STARTCHILDAPP, or the 1166 // app will be terminated automatically 1167 // when the WPS terminates! 1168 arc = ERROR_BAD_FORMAT; 1169 // @@todo we can probably do better 1170 // V0.9.16 (2001-10-19) [umoeller] 1171 1172 // _Pmpf((__FUNCTION__ ": got happ 0x%lX", happ)); 1173 } 1174 } 1126 1175 1127 1176 xstrClear(&strParamsPatched); … … 1130 1179 } // end if (ProgDetails.pszExecutable) 1131 1180 1132 return (happ); 1133 } 1134 1135 1181 _Pmpf((__FUNCTION__ ": returning %d", arc)); 1182 1183 return (arc); 1184 } 1185 1186 /* 1187 *@@ appWaitForApp: 1188 * waits for the specified application to terminate 1189 * and returns its exit code. 1190 * 1191 *@@added V0.9.9 (2001-03-07) [umoeller] 1192 */ 1193 1194 BOOL appWaitForApp(HWND hwndNotify, // in: notify window 1195 HAPP happ, // in: app to wait for 1196 PULONG pulExitCode) // out: exit code (ptr can be NULL) 1197 { 1198 BOOL brc = FALSE; 1199 1200 if (happ) 1201 { 1202 // app started: 1203 // enter a modal message loop until we get the 1204 // WM_APPTERMINATENOTIFY for happ. Then we 1205 // know the app is done. 1206 HAB hab = WinQueryAnchorBlock(hwndNotify); 1207 QMSG qmsg; 1208 // ULONG ulXFixReturnCode = 0; 1209 while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0)) 1210 { 1211 if ( (qmsg.msg == WM_APPTERMINATENOTIFY) 1212 && (qmsg.hwnd == hwndNotify) 1213 && (qmsg.mp1 == (MPARAM)happ) 1214 ) 1215 { 1216 // xfix has terminated: 1217 // get xfix return code from mp2... this is: 1218 // -- 0: everything's OK, continue. 1219 // -- 1: handle section was rewritten, restart Desktop 1220 // now. 1221 if (pulExitCode) 1222 *pulExitCode = (ULONG)qmsg.mp2; 1223 brc = TRUE; 1224 // do not dispatch this 1225 break; 1226 } 1227 1228 WinDispatchMsg(hab, &qmsg); 1229 } 1230 } 1231 1232 return (brc); 1233 } 1234 1235 /* 1236 *@@ appQuickStartApp: 1237 * shortcut for simply starting an app and 1238 * waiting until it's finished. 1239 * 1240 * On errors, NULLHANDLE is returned. 1241 * 1242 * If pulReturnCode != NULL, it receives the 1243 * return code of the app. 1244 * 1245 *@@added V0.9.16 (2001-10-19) [umoeller] 1246 */ 1247 1248 HAPP appQuickStartApp(const char *pcszFile, 1249 ULONG ulProgType, // e.g. PROG_PM 1250 const char *pcszArgs, 1251 PULONG pulExitCode) 1252 { 1253 PROGDETAILS pd = {0}; 1254 HAPP happ, 1255 happReturn = NULLHANDLE; 1256 CHAR szDir[CCHMAXPATH] = ""; 1257 PCSZ p; 1258 HWND hwndObject; 1259 1260 pd.Length = sizeof(pd); 1261 pd.progt.progc = ulProgType; 1262 pd.progt.fbVisible = SHE_VISIBLE; 1263 pd.pszExecutable = (PSZ)pcszFile; 1264 pd.pszParameters = (PSZ)pcszArgs; 1265 if (p = strrchr(pcszFile, '\\')) 1266 { 1267 strhncpy0(szDir, 1268 pcszFile, 1269 p - pcszFile); 1270 pd.pszStartupDir = szDir; 1271 } 1272 1273 if ( (hwndObject = winhCreateObjectWindow(WC_STATIC, NULL)) 1274 && (!appStartApp(hwndObject, 1275 &pd, 1276 0, 1277 &happ)) 1278 ) 1279 { 1280 if (appWaitForApp(hwndObject, 1281 happ, 1282 pulExitCode)) 1283 happReturn = happ; 1284 } 1285 1286 return (happReturn); 1287 }
Note:
See TracChangeset
for help on using the changeset viewer.