source: trunk/dll/systemf.c@ 544

Last change on this file since 544 was 540, checked in by root, 19 years ago

runemf2: rework termination queue logic to work for multiple threads

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.9 KB
RevLine 
[78]1
2/***********************************************************************
3
4 $Id: systemf.c 540 2006-11-04 21:18:01Z root $
5
6 System Interfaces
7
8 Copyright (c) 1993-98 M. Kimes
[330]9 Copyright (c) 2003, 2006 Steven H.Levine
[78]10
[330]11 21 Nov 03 SHL Comments
12 31 Jul 04 SHL Indent -i2
13 01 Aug 04 SHL Rework lstrip/rstrip usage
14 17 Jul 06 SHL Use Runtime_Error
[373]15 26 Jul 06 SHL Use convert_nl_to_nul
[441]16 15 Aug 06 SHL More error popups
[519]17 01 Nov 06 SHL runemf2: temp fix for hung windows caused by termq errors
[540]18 03 Nov 06 SHL runemf2: rework termination queue logic to work for multiple threads
[78]19
20***********************************************************************/
21
[2]22#define INCL_WIN
23#define INCL_WINERRORS
24#define INCL_DOS
25#define INCL_DOSERRORS
[330]26#include <os2.h>
[2]27
28#include <stdlib.h>
29#include <stdio.h>
30#include <stdarg.h>
31#include <string.h>
32#include <ctype.h>
33#include <time.h>
[330]34
[2]35#include "fm3dll.h"
36#include "fm3dlg.h"
37#include "fm3str.h"
38
[330]39static PSZ pszSrcFile = __FILE__;
40
[2]41#pragma alloc_text(SYSTEMF,ShowSession,ExecOnList,runemf2)
42
[105]43#define MAXSTRG (4096) /* used to build command line strings */
[2]44
[519]45//== ShowSession() bring session for foreground ==
[2]46
[105]47BOOL ShowSession(HWND hwnd, PID pid)
[78]48{
[105]49 HSWITCH hswitch;
50 SWCNTRL swctl;
51 ULONG rc;
[2]52
[519]53 hswitch = WinQuerySwitchHandle(pid ? (HWND)0 : hwnd, pid);
[441]54 if (hswitch) {
[105]55 rc = WinQuerySwitchEntry(hswitch, &swctl);
[441]56 if (!rc) {
[105]57 if (swctl.idProcess == pid && swctl.uchVisibility == SWL_VISIBLE)
58 rc = WinSwitchToProgram(hswitch);
59 if (!rc)
60 return TRUE;
[78]61 // else saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Failed: %lu/%lx",rc,rc);
[2]62
[105]63 }
64 }
65 return FALSE;
[2]66}
67
[519]68//== ExecOnList() Invoke runemf2 for command and file/directory list ==
69
[105]70int ExecOnList(HWND hwnd, char *command, int flags, char *tpath,
71 char **list, char *prompt)
[78]72{
[105]73 /* executes the command once for all files in list */
[2]74
[105]75 char path[CCHMAXPATH], commandline[2048], modpath[CCHMAXPATH], listfile[CCHMAXPATH],
76 *p, *pp, drive, *file, *ext, *dot;
[2]77 register int x;
[105]78 BOOL spaces;
[2]79
[441]80 if (!command || !*command) {
81 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
[105]82 return -1;
[441]83 }
[2]84 *listfile = 0;
[123]85 bstrip(command);
[2]86
87 *path = 0;
[105]88 if (tpath && *tpath)
89 strcpy(path, tpath);
[441]90 else if (*command != '<' || !strchr(command, '>')) {
[105]91 strcpy(path, command + (*command == '"'));
92 if (*command == '\"')
93 p = strchr(path, '\"');
[2]94 else
[105]95 p = strchr(path, ' ');
96 if (p)
[2]97 *p = 0;
[105]98 p = strrchr(path, '\\');
99 if (!p)
100 p = strrchr(path, ':');
[441]101 if (p) {
102 if (*p == ':') {
[105]103 p++;
104 *p = '\\';
105 p++;
[2]106 }
107 *p = 0;
108 }
109 else
110 *path = 0;
111 }
[441]112 if (!*path) {
[105]113 if (list && list[0])
114 strcpy(path, list[0]);
115 p = strrchr(path, '\\');
116 if (!p)
117 p = strrchr(path, ':');
[441]118 if (p) {
119 if (*p == ':') {
[105]120 p++;
121 *p = '\\';
122 p++;
[2]123 }
124 *p = 0;
125 }
126 else
127 *path = 0;
128 }
129 *modpath = 0;
[105]130 if (list && list[0])
131 strcpy(modpath, list[0]);
132 p = strrchr(modpath, '\\');
133 if (!p)
134 p = strrchr(modpath, ':');
[441]135 if (p) {
136 if (*p == ':') {
[2]137 p++;
138 *p = '\\';
139 p++;
140 }
141 *p = 0;
142 }
143 else
144 *modpath = 0;
[105]145 if (!*modpath)
146 strcpy(modpath, path);
147 if (*path)
[2]148 MakeFullName(path);
[105]149 if (*modpath)
[2]150 MakeFullName(modpath);
[105]151 if (IsFullName(path))
152 drive = toupper(*path);
153 else
154 drive = 0;
[2]155
[105]156 p = command; // substitue for special % sequences
[2]157
[105]158 pp = commandline;
159 *commandline = 0;
[441]160 while (*p) {
161 if (*p == '%') {
162 switch (*(p + 1)) {
[105]163 case '!': /* write list to file, add filename */
[441]164 if (list) {
165 if (!*listfile) {
[105]166 FILE *fp;
[2]167
[105]168 save_dir2(listfile);
169 if (listfile[strlen(listfile) - 1] != '\\')
170 strcat(listfile, "\\");
171 sprintf(&listfile[strlen(listfile)], "%s%03x",
172 LISTTEMPROOT, (clock() & 4095L));
[330]173 fp = xfopen(listfile, "w",pszSrcFile,__LINE__);
[441]174 if (fp) {
[105]175 for (x = 0; list[x]; x++)
176 {
177 fputs(list[x], fp);
178 if (list[x + 1])
179 fputc('\n', fp);
180 }
181 fclose(fp);
182 }
183 }
184 strcpy(pp, listfile);
185 pp += strlen(listfile);
186 }
187 p += 2;
188 break;
[2]189
[105]190 case 'c': /* add name of command processor */
191 {
192 char *env = GetCmdSpec(FALSE);
[2]193
[441]194 if (needs_quoting(env) && !strchr(env, '\"')) {
[105]195 *pp = '\"';
196 pp++;
197 spaces = TRUE;
198 }
199 else
200 spaces = FALSE;
201 strcpy(pp, env);
202 p += 2;
203 pp += strlen(env);
[441]204 if (spaces) {
[105]205 *pp = '\"';
206 pp++;
207 }
208 }
209 break;
[2]210
[105]211 case 't': /* add Target directory */
[441]212 if (needs_quoting(targetdir) && !strchr(targetdir, '\"')) {
[105]213 *pp = '\"';
214 pp++;
215 spaces = TRUE;
216 }
217 else
218 spaces = FALSE;
219 strcpy(pp, targetdir);
220 p += 2;
221 pp += strlen(targetdir);
[441]222 if (spaces) {
[105]223 *pp = '\"';
224 pp++;
225 }
226 break;
[2]227
[105]228 case '$': /* add drive letter */
229 if (drive)
230 *pp = drive;
[441]231 else {
[105]232 ULONG ulDriveNum = 3L, ulDriveMap;
[2]233
[105]234 DosQCurDisk(&ulDriveNum, &ulDriveMap);
235 *pp = (char) (ulDriveNum + '@');
236 }
237 pp++;
238 p += 2;
239 break;
[2]240
[105]241 case 'U': /* add path of first list component */
242 case 'u':
[441]243 if (*modpath) {
244 if (needs_quoting(modpath) && !strchr(modpath, '\"')) {
[105]245 spaces = TRUE;
246 *pp = '\"';
247 pp++;
248 }
249 else
250 spaces = FALSE;
[441]251 if (*(p + 1) == 'u') {
[105]252 strcpy(pp, modpath);
253 pp += strlen(modpath);
254 }
[441]255 else {
[105]256 strcpy(pp, modpath + 2);
257 pp += strlen(modpath + 2);
258 }
[441]259 if (spaces) {
260 if (modpath[strlen(modpath) - 1] == '\\') {
[105]261 *pp = '\\';
262 pp++;
263 }
264 *pp = '\"';
265 pp++;
266 }
267 }
[441]268 else {
[105]269 char temp[CCHMAXPATH];
[2]270
[105]271 save_dir2(temp);
[441]272 if (needs_quoting(temp) && !strchr(temp, '\"')) {
[105]273 spaces = TRUE;
274 *pp = '\"';
275 pp++;
276 }
277 else
278 spaces = FALSE;
279 strcpy(pp, temp);
280 pp += strlen(temp);
[441]281 if (spaces) {
282 if (temp[strlen(temp) - 1] == '\\') {
[105]283 *pp = '\\';
284 pp++;
285 }
286 *pp = '\"';
287 pp++;
288 }
289 }
290 p += 2;
291 break;
[2]292
[105]293 case 'P': /* add path of execution */
294 case 'p':
[441]295 if (*path) {
296 if (needs_quoting(path) && !strchr(path, '\"')) {
[105]297 spaces = TRUE;
298 *pp = '\"';
299 pp++;
300 }
301 else
302 spaces = FALSE;
[441]303 if (*(p + 1) == 'p') {
[105]304 strcpy(pp, path);
305 pp += strlen(path);
306 }
[441]307 else {
[105]308 strcpy(pp, path + 2);
309 pp += strlen(path + 2);
310 }
[441]311 if (spaces) {
312 if (path[strlen(path) - 1] == '\\') {
[105]313 *pp = '\\';
314 pp++;
315 }
316 *pp = '\"';
317 pp++;
318 }
319 }
[441]320 else {
[105]321 char temp[CCHMAXPATH];
[2]322
[105]323 save_dir2(temp);
[441]324 if (needs_quoting(temp) && !strchr(temp, '\"')) {
[105]325 spaces = TRUE;
326 *pp = '\"';
327 pp++;
328 }
329 else
330 spaces = FALSE;
331 strcpy(pp, temp);
332 pp += strlen(temp);
[441]333 if (spaces) {
334 if (temp[strlen(temp) - 1] == '\\') {
[105]335 *pp = '\\';
336 pp++;
337 }
338 *pp = '\"';
339 pp++;
340 }
341 }
342 p += 2;
343 break;
[2]344
[105]345 case 'D':
[441]346 if (hwndMain) {
[105]347 PCNRITEM pci;
[2]348
[105]349 pci = (PCNRITEM) WinSendMsg(WinWindowFromID(WinWindowFromID(
350 hwndTree, FID_CLIENT), TREE_CNR),
351 CM_QUERYRECORDEMPHASIS,
352 MPFROMLONG(CMA_FIRST),
353 MPFROMSHORT(CRA_CURSORED));
[441]354 if (pci && (int) pci != -1 && *pci -> szFileName) {
[105]355 if (needs_quoting(pci -> szFileName) &&
356 !strchr(pci -> szFileName, '\"'))
357 {
358 *pp = '\"';
359 pp++;
360 spaces = TRUE;
361 }
362 else
363 spaces = FALSE;
364 strcpy(pp, pci -> szFileName);
365 pp += strlen(pci -> szFileName);
[441]366 if (spaces) {
[105]367 *pp = '\"';
368 pp++;
369 }
370 }
371 }
372 p += 2;
373 break;
[2]374
[105]375 case 'd':
[441]376 if (hwndMain) {
[105]377 HENUM henum;
378 char retstr[CCHMAXPATH];
379 HWND hwndC, hwndDir;
380 USHORT id;
381 BOOL first = TRUE;
[2]382
[105]383 henum = WinBeginEnumWindows(hwndMain);
[441]384 while ((hwndC = WinGetNextWindow(henum)) != NULLHANDLE) {
385 if (hwndC != hwndTree) {
[105]386 id = WinQueryWindowUShort(hwndC, QWS_ID);
[441]387 if (id) {
[105]388 hwndDir = WinWindowFromID(hwndC, FID_CLIENT);
[441]389 if (hwndDir) {
[105]390 hwndDir = WinWindowFromID(hwndDir, DIR_CNR);
[441]391 if (hwndDir) {
[105]392 *retstr = 0;
393 WinSendMsg(hwndC, UM_CONTAINERDIR, MPFROMP(retstr), MPVOID);
[441]394 if (*retstr) {
395 if (!first) {
[105]396 *pp = ' ';
397 pp++;
398 }
399 first = FALSE;
[441]400 if (needs_quoting(retstr) && !strchr(retstr, '\"')) {
[105]401 *pp = '\"';
402 pp++;
403 spaces = TRUE;
404 }
405 else
406 spaces = FALSE;
407 strcpy(pp, retstr);
408 pp += strlen(retstr);
[441]409 if (spaces) {
[105]410 *pp = '\"';
411 pp++;
412 }
413 }
414 }
415 }
416 }
417 }
418 }
419 WinEndEnumWindows(henum);
420 }
421 p += 2;
422 break;
[2]423
[105]424 case '%':
425 *pp = '%';
426 pp++;
427 p += 2;
428 break;
[2]429
[105]430 case 'R':
431 case 'F':
432 case 'A':
433 case 'r':
434 case 'f':
435 case 'a':
436 case 'e':
[441]437 if (list) {
[105]438 for (x = 0; list[x]; x++)
439 {
440 file = strrchr(list[x], '\\');
441 if (!file)
442 file = strrchr(list[x], ':');
443 if (file)
444 file++;
445 else
446 file = list[x];
447 ext = strrchr(file, '.');
448 dot = ext;
449 if (ext)
450 ext++;
[441]451 switch (*(p + 1)) {
[105]452 case 'R':
453 case 'r':
454 if (pp + strlen(list[x]) > commandline + 1250)
455 goto BreakOut;
[441]456 if (*(p + 1) == 'r') {
[105]457 strcpy(pp, list[x]);
458 pp += strlen(list[x]);
459 }
[441]460 else {
[105]461 strcpy(pp, list[x] + 2);
462 pp += strlen(list[x] + 2);
463 }
464 break;
[2]465
[105]466 case 'F':
467 case 'f':
468 if (*(p + 1) == 'F' && dot)
469 *dot = 0;
470 if (pp + strlen(file) > commandline + 1250)
471 goto BreakOut;
[441]472 if (needs_quoting(file)) {
[105]473 spaces = TRUE;
474 *pp = '\"';
475 pp++;
476 }
477 else
478 spaces = FALSE;
479 strcpy(pp, file);
480 pp += strlen(file);
481 if (*(p + 1) == 'F' && dot)
482 *dot = '.';
[441]483 if (spaces) {
484 if (*(pp - 1) != '\"') {
[105]485 *pp = '\"';
486 pp++;
487 }
488 }
489 break;
[2]490
[105]491 case 'A':
492 case 'a':
493 if (pp + strlen(list[x]) > commandline + 1250)
494 goto BreakOut;
[441]495 if (needs_quoting(list[x]) && !strchr(list[x], '\"')) {
[105]496 spaces = TRUE;
497 *pp = '\"';
498 pp++;
499 }
500 else
501 spaces = FALSE;
[441]502 if (*(p + 1) == 'a') {
[105]503 strcpy(pp, list[x]);
504 pp += strlen(list[x]);
505 }
[441]506 else {
[105]507 strcpy(pp, list[x] + 2);
508 pp += strlen(list[x] + 2);
509 }
[441]510 if (spaces) {
511 if (list[x][strlen(list[x]) - 1] == '\\') {
[105]512 *pp = '\\';
513 pp++;
514 }
515 *pp = '\"';
516 pp++;
517 }
518 break;
[2]519
[105]520 case 'e':
[441]521 if (ext) {
[105]522 if (pp + strlen(ext) > commandline + 1250)
523 goto BreakOut;
[441]524 if (needs_quoting(ext)) {
[105]525 spaces = TRUE;
526 *pp = '\"';
527 pp++;
[2]528 }
[105]529 else
530 spaces = FALSE;
531 strcpy(pp, ext);
532 pp += strlen(ext);
[441]533 if (spaces) {
534 if (*(pp - 1) != '\"') {
[105]535 *pp = '\"';
536 pp++;
537 }
[2]538 }
[105]539 }
540 break;
541 }
[441]542 if (list[x + 1]) {
[105]543 *pp = ' ';
544 pp++;
545 }
546 }
[2]547 }
[105]548 p += 2;
549 break;
[2]550
[105]551 default:
552 *pp = *p;
553 p++;
554 pp++;
555 break;
556 }
557 }
[441]558 else {
[105]559 *pp = *p;
560 pp++;
561 p++;
562 }
563 *pp = 0;
564 }
565
[2]566BreakOut:
567
[105]568 {
569 EXECARGS ex;
570 ULONG size;
571 int ret;
[2]572
[105]573 memset(&ex, 0, sizeof(EXECARGS));
574 size = sizeof(ex.environment) - 1;
575 PrfQueryProfileData(fmprof, FM3Str, command, ex.environment, &size);
[441]576 if (flags & PROMPT) {
577 /* allow editing command line */
[105]578 ex.flags = (flags & (~PROMPT));
579 ex.commandline = commandline;
580 strcpy(ex.path, path);
581 if (prompt)
582 strcpy(ex.title, prompt);
583 ret = WinDlgBox(HWND_DESKTOP, hwnd, CmdLineDlgProc, FM3ModHandle,
584 EXEC_FRAME, &ex);
585 if (ret != 1)
586 return (ret == 0) ? -1 : -2;
587 }
588 else
589 ex.flags = flags;
590 ex.flags &= (~PROMPT);
591 return runemf2(ex.flags, hwnd, path,
592 (*ex.environment) ? ex.environment : NULL,
593 "%s", commandline);
594 }
[2]595}
596
[519]597//== runemf2() run requested app, return -1 if problem starting else return app rc ==
[441]598
[540]599int runemf2(int type, HWND hwnd, char *pszDirectory, char *pszEnvironment,
[105]600 char *formatstring,...)
[78]601{
[105]602 /* example:
603
[2]604 * status = runemf2(SEPARATE | WINDOWED,
605 * hwnd,
606 * NullStr,
607 * NULL,
608 * "%s /C %s",
609 * getenv("COMSPEC"),
610 * batchfilename);
[105]611 *
612 * use (HWND)0 for hwnd if window handle not handy.
613 */
[2]614
615 /*
616 * type bitmapped flag -- see FM3DLL.H
617 */
618
[105]619 va_list parguments;
620 int ret = -1;
[540]621 RESULTCODES results;
[519]622 STARTDATA sdata;
[105]623 REQUESTDATA rq;
[540]624 ULONG ulSessID, apptype, ulLength, ctr;
[105]625 PID sessPID;
626 BOOL wasquote;
[540]627 char *pszPgm, *pszArgs = NULL;
628 char szObject[32] = "", *p, szSavedir[CCHMAXPATH];
629 BOOL useTermQ = FALSE;
630 char szTempdir[CCHMAXPATH];
631
[519]632 typedef struct {
633 USHORT usSessID;
634 USHORT usRC;
635 } TERMINFO;
636
[540]637 TERMINFO *pTermInfo;
[105]638 BYTE bPriority;
639 APIRET rc;
[519]640 PIB *ppib;
641 TIB *ptib;
[2]642
[540]643 // Shared by all threads
644# define TERMQ_BASE_NAME "\\QUEUES\\FM3WAIT"
645 static char szTermQName[30];
646 static HQUEUE hTermQ;
647 static HEV hTermQSem;
648
649 if (pszDirectory && *pszDirectory) {
650 if (!DosQueryPathInfo(pszDirectory,
[105]651 FIL_QUERYFULLNAME,
[540]652 szTempdir,
653 sizeof(szTempdir)))
654 pszDirectory = szTempdir;
[105]655 }
[2]656
[105]657 if (!hwnd)
658 hwnd = HWND_DESKTOP;
[2]659
[540]660 rc = DosAllocMem((PVOID)&pszPgm,
[105]661 MAXSTRG,
662 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
[330]663 if (rc) {
664 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
[105]665 return -1;
[330]666 }
[2]667
[540]668 *szSavedir = 0;
[2]669
[540]670 *pszPgm = 0;
[105]671 va_start(parguments,
672 formatstring);
[540]673 vsprintf(pszPgm,
[105]674 formatstring,
675 parguments);
676 va_end(parguments);
[2]677
[540]678 if (pszEnvironment) {
679 p = &pszEnvironment[strlen(pszEnvironment)] + 1;
[105]680 *p = 0;
[540]681 p = pszEnvironment;
[373]682 while ((p = convert_nl_to_nul(p)) != NULL)
683 ; // loop
[105]684 }
[2]685
[540]686 if (!*pszPgm) {
[105]687 p = GetCmdSpec(FALSE);
[540]688 strcpy(pszPgm, p);
689 if (!*pszPgm) {
[441]690 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
[105]691 return -1;
[441]692 }
[105]693 }
[2]694
[540]695 if (*pszPgm) {
696 if (*pszPgm == '<' && strchr(pszPgm, '>')) {
[441]697 /* is a workplace object */
[105]698 HOBJECT hWPSObject;
699 char temp;
[2]700
[540]701 p = strchr(pszPgm, '>');
[105]702 p++;
703 temp = *p;
[330]704 if (temp) {
[540]705 rc = DosAllocMem((PVOID)&pszArgs,
[105]706 MAXSTRG * 2,
707 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
[330]708 if (rc)
[540]709 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
[330]710 }
[105]711 else
[540]712 pszArgs = NULL;
[105]713 *p = 0;
714 /* Find the handle of the WPS object */
[540]715 hWPSObject = WinQueryObject(pszPgm);
[105]716 *p = temp;
[441]717 if (hWPSObject != NULLHANDLE) {
[540]718 if (pszArgs && *p) {
719 sprintf(pszArgs,"OPEN=DEFAULT;PARAMETERS=\"%s\"",p);
720 WinSetObjectData(hWPSObject,pszArgs);
[105]721 }
722 else
[441]723 WinSetObjectData(hWPSObject,"OPEN=DEFAULT");
[105]724 ret = 0;
725 }
726 goto ObjectInterrupt;
727 }
[2]728
[105]729 if ((type & 15) == SYNCHRONOUS ||
730 (type & 15) == ASYNCHRONOUS ||
731 (type & 15) == DETACHED)
732 {
[540]733 strip_lead_char(" \t", pszPgm);
734 p = pszPgm;
[105]735 wasquote = FALSE;
736 while (*p &&
737 (wasquote ||
738 (*p != ' ' &&
739 *p != '\t')))
740 {
[441]741 if (*p == '\"') {
742 if (!wasquote) {
[105]743 wasquote = TRUE;
744 memmove(p,
745 p + 1,
746 strlen(p));
747 while (*p == ' ' ||
748 *p == '\t')
749 p++;
750 }
[441]751 else {
[105]752 memmove(p,
753 p + 1,
754 strlen(p));
755 break;
756 }
757 }
758 else
759 p++;
760 }
[441]761 if (*p) {
[105]762 *p = 0;
763 p++;
764 }
765 else
[540]766 p = pszPgm;
[105]767 p[strlen(p) + 1] = 0; /* double-terminate args */
[540]768 if (*pszPgm) {
769 if (!strchr(pszPgm, '\\') &&
770 !strchr(pszPgm, ':') &&
771 pszDirectory &&
772 *pszDirectory)
[105]773 {
[540]774 save_dir2(szSavedir);
775 switch_to(pszDirectory);
[105]776 }
[540]777 rc = DosQAppType(pszPgm,&apptype);
778 if (!strchr(pszPgm, '\\') &&
779 !strchr(pszPgm, ':') &&
780 pszDirectory &&
781 *pszDirectory)
782 switch_to(szSavedir);
[441]783 if (rc) {
784 // fixme to be in fm2dll.str
[540]785 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosQAppType failed for %s.", pszPgm);
786 DosFreeMem(pszPgm);
787 if (pszArgs)
788 DosFreeMem(pszArgs);
[105]789 return -1;
790 }
[441]791 if (apptype) {
[105]792 if ((apptype & FAPPTYP_DLL) || (apptype & FAPPTYP_VIRTDRV) ||
793 (apptype & FAPPTYP_PHYSDRV) || (apptype & FAPPTYP_PROTDLL))
794 {
[441]795 // fixme to be in fm2dll.str
[540]796 Runtime_Error(pszSrcFile, __LINE__, "apptype 0x%x unexpected for %s.", apptype, pszPgm);
797 if (pszPgm)
798 DosFreeMem(pszPgm);
799 if (pszArgs)
800 DosFreeMem(pszArgs);
[105]801 return -1;
802 }
803 if ((apptype & FAPPTYP_DOS) || (apptype & FAPPTYP_WINDOWSREAL) ||
804 (apptype & FAPPTYP_WINDOWSPROT) || (apptype & 0x1000))
805 {
[540]806 Runtime_Error(pszSrcFile, __LINE__, "apptype 0x%x unexpected for %s.", apptype, pszPgm);
807 if (pszPgm)
808 DosFreeMem(pszPgm);
809 if (pszArgs)
810 DosFreeMem(pszArgs);
[105]811 return -1;
812 }
813 }
[540]814 memset(&results, 0, sizeof(results));
815 if (pszDirectory && *pszDirectory) {
816 save_dir2(szSavedir);
817 switch_to(pszDirectory);
[105]818 }
[540]819 ret = DosExecPgm(szObject, sizeof(szObject),
820 ((type & 15) == ASYNCHRONOUS ? EXEC_ASYNC : 0) +
821 ((type & 15) == DETACHED ? EXEC_BACKGROUND : 0),
822 pszPgm, pszEnvironment, &results, pszPgm);
823 if (pszDirectory && *pszDirectory)
824 switch_to(szSavedir);
[330]825 if (ret) {
826 Dos_Error(MB_ENTER,ret,hwnd,pszSrcFile,__LINE__,
[540]827 GetPString(IDS_DOSEXECPGMFAILEDTEXT), pszPgm);
[330]828 }
[105]829 }
830 }
[441]831 else {
[519]832 if (~type & FULLSCREEN)
[105]833 type |= WINDOWED;
[540]834 rc = DosAllocMem((PVOID) & pszArgs, MAXSTRG * 2,
[105]835 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
[441]836 if (rc) {
[540]837 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
838 DosFreeMem(pszPgm);
[105]839 return -1;
840 }
[540]841 *pszArgs = 0;
842 memset(&sdata, 0, sizeof(sdata));
843 strip_lead_char(" \t", pszPgm);
844 p = pszPgm;
[105]845 wasquote = FALSE;
[441]846 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
847 if (*p == '\"') {
848 if (!wasquote) {
[105]849 wasquote = TRUE;
850 memmove(p, p + 1, strlen(p));
851 while (*p == ' ' || *p == '\t')
852 p++;
853 }
[441]854 else {
[105]855 memmove(p, p + 1, strlen(p));
856 break;
857 }
858 }
859 else
860 p++;
[540]861 } // while
[441]862 if (*p) {
[105]863 *p = 0;
864 p++;
865 }
866 else
867 p = NullStr;
868 if (*p)
[540]869 strcpy(pszArgs, p);
[2]870
[540]871 p = strrchr(pszPgm, '.');
[441]872 if (p) {
[105]873 char temp[CCHMAXPATH + 1];
[2]874
[441]875 if (!stricmp(p, ".BAT")) {
[540]876 strcpy(temp, pszPgm);
877 strcpy(pszPgm, pszArgs);
878 strcpy(pszArgs, "/C ");
879 strcat(pszArgs, temp);
880 strcat(pszArgs, " ");
881 strcat(pszArgs, pszPgm);
882 strcpy(pszPgm, GetCmdSpec(TRUE)); // DOS
[105]883 }
[540]884 else if (!stricmp(p, ".CMD") || !stricmp(p, ".BTM")) {
885 // Assume 4OS2 is BTM
886 strcpy(temp, pszPgm);
887 strcpy(pszPgm, pszArgs);
888 strcpy(pszArgs, "/C ");
889 strcat(pszArgs, temp);
890 strcat(pszArgs, " ");
891 strcat(pszArgs, pszPgm);
892 strcpy(pszPgm, GetCmdSpec(FALSE)); // OS/2
[105]893 }
894 }
[2]895
[105]896 /* goddamned OS/2 limit */
[2]897
[540]898 if (strlen(pszPgm) + strlen(pszArgs) > 1024)
899 pszArgs[1024 - strlen(pszPgm)] = 0;
[2]900
[540]901 if (!strchr(pszPgm, '\\') &&
902 !strchr(pszPgm, ':') &&
903 pszDirectory &&
904 *pszDirectory)
[105]905 {
[540]906 save_dir2(szSavedir);
907 switch_to(pszDirectory);
[105]908 }
[540]909 rc = DosQAppType(pszPgm,&apptype);
910 if (!strchr(pszPgm, '\\') &&
911 !strchr(pszPgm, ':') &&
912 pszDirectory &&
913 *pszDirectory)
914 switch_to(szSavedir);
[441]915 if (rc) {
916 // fixme to be in fm2dll.str
[540]917 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosQAppType failed for %s.", pszPgm);
918 DosFreeMem(pszPgm);
919 if (pszArgs)
920 DosFreeMem(pszArgs);
[105]921 return -1;
922 }
[2]923
[441]924 if (apptype) {
[540]925 if (apptype & (FAPPTYP_DLL | FAPPTYP_VIRTDRV | FAPPTYP_PHYSDRV | FAPPTYP_PROTDLL))
[105]926 {
[441]927 // fixme to be in fm2dll.str
[540]928 Runtime_Error(pszSrcFile, __LINE__, "apptype %d unexpected for %s.", pszPgm);
929 DosFreeMem(pszPgm);
930 if (pszArgs)
931 DosFreeMem(pszArgs);
[105]932 return -1;
933 }
[540]934 apptype &= ~FAPPTYP_BOUND;
935 if (apptype & (FAPPTYP_DOS | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
[105]936 {
[540]937 if (apptype & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
[105]938 {
[540]939 if (~type & FULLSCREEN &&
940 apptype & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
[105]941 {
[540]942 ret = RunSeamless(pszPgm, pszArgs, hwnd);
943 if (pszPgm)
944 DosFreeMem(pszPgm);
945 if (pszArgs)
946 DosFreeMem(pszArgs);
[441]947 return ret ? 0 : -1;
[105]948 }
[441]949 else {
[540]950 strcat(pszPgm, " ");
951 strcat(pszPgm, pszArgs);
952 *pszArgs = 0;
953 if (apptype & (FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT31))
954 strcat(pszArgs, "/3 ");
955 strcat(pszArgs, pszPgm);
956 strcpy(pszPgm, "WINOS2.COM");
[105]957 }
958 }
[441]959 else {
[540]960 if (~type & FULLSCREEN) {
[105]961 type |= WINDOWED;
962 apptype = SSF_TYPE_WINDOWEDVDM;
963 }
[441]964 else {
[540]965 type &= ~WINDOWED;
[105]966 apptype = SSF_TYPE_VDM;
967 }
968 }
969 }
[441]970 else if (apptype & FAPPTYP_32BIT) {
[540]971 apptype &= ~FAPPTYP_32BIT;
[105]972 if (apptype == FAPPTYP_WINDOWAPI)
973 apptype = SSF_TYPE_PM;
974 else if (apptype == FAPPTYP_WINDOWCOMPAT)
975 apptype = SSF_TYPE_WINDOWABLEVIO;
[441]976 else if (apptype == FAPPTYP_NOTWINDOWCOMPAT) {
[105]977 apptype = SSF_TYPE_FULLSCREEN;
[540]978 type &= ~WINDOWED;
[105]979 type |= FULLSCREEN;
980 }
981 else /* ? */
982 apptype = SSF_TYPE_WINDOWABLEVIO;
983 }
984 else if (apptype == FAPPTYP_WINDOWAPI)
985 apptype = SSF_TYPE_PM;
986 else if (apptype == FAPPTYP_WINDOWCOMPAT)
987 apptype = SSF_TYPE_WINDOWABLEVIO;
[441]988 else if (apptype == FAPPTYP_NOTWINDOWCOMPAT) {
[540]989 type &= ~WINDOWED;
[105]990 apptype = SSF_TYPE_FULLSCREEN;
991 }
992 else
993 apptype = SSF_TYPE_DEFAULT;
[540]994 if ((type & FULLSCREEN || ~type & WINDOWED) &&
[105]995 apptype == SSF_TYPE_WINDOWABLEVIO)
996 {
997 apptype = SSF_TYPE_FULLSCREEN;
998 }
[519]999 // fixme parens?
[540]1000 else if (type & FULLSCREEN ||
1001 (type & WINDOWED && apptype == SSF_TYPE_WINDOWEDVDM))
[105]1002 apptype = SSF_TYPE_VDM;
1003 }
[540]1004 if (apptype == SSF_TYPE_WINDOWEDVDM && type & SEPARATEKEEP) {
[519]1005 type &= ~SEPARATEKEEP;
[105]1006 type |= SEPARATE;
1007 }
[2]1008
[519]1009 DosGetInfoBlocks(&ptib, &ppib);
1010
[540]1011 if (~type & WAIT)
1012 useTermQ = FALSE;
[519]1013 else {
[540]1014 rc = 0;
1015 DosEnterCritSec();
1016 if (!hTermQ) {
1017 // Create term queue and event semaphore just once
1018 sprintf(szTermQName, TERMQ_BASE_NAME "_%x", ppib->pib_ulpid);
1019 rc = DosCreateQueue(&hTermQ, QUE_FIFO | QUE_CONVERT_ADDRESS, szTermQName);
1020 if (rc) {
1021 hTermQ = (HQUEUE)0; // Try to survive
1022 DosExitCritSec();
1023 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosCreateQueue");
1024 }
1025 else {
1026 rc = DosCreateEventSem(NULL,(PHEV)&hTermQSem,0,FALSE);
1027 if (rc) {
1028 hTermQSem = (HEV)0; // Try to survive
1029 DosCloseQueue(hTermQ);
1030 hTermQ = (HQUEUE)0; // Try to survive
1031 DosExitCritSec();
1032 Dos_Error(MB_ENTER,rc,HWND_DESKTOP,pszSrcFile,__LINE__,"DoCreateEventSem");
1033 }
1034 // if (!rc)
1035 // fprintf(stderr,"runemf2 qcreated ptib %x hTermQ %x\n",ptib,hTermQ);
1036 }
1037 } // if 1st time
1038 useTermQ = hTermQ && hTermQSem;
1039 if (!rc)
1040 DosExitCritSec();
1041 } // if wait
[519]1042 sdata.Length = sizeof(sdata);
1043 sdata.Related = type & (WAIT | CHILD) ?
1044 SSF_RELATED_CHILD : SSF_RELATED_INDEPENDENT;
1045 sdata.FgBg = type & BACKGROUND ? SSF_FGBG_BACK : SSF_FGBG_FORE;
1046 sdata.TraceOpt = SSF_TRACEOPT_NONE;
1047 sdata.PgmTitle = NULL;
[540]1048 sdata.PgmName = pszPgm;
1049 sdata.PgmInputs = *pszArgs ? pszArgs : NULL;
1050 sdata.TermQ = useTermQ ? szTermQName : NULL;
1051 sdata.Environment = pszEnvironment;
[519]1052 sdata.InheritOpt = SSF_INHERTOPT_PARENT;
1053 sdata.SessionType = (USHORT)apptype;
[540]1054 sdata.ObjectBuffer = szObject;
1055 sdata.ObjectBuffLen = sizeof(szObject);
[519]1056 sdata.IconFile = NULL;
1057 sdata.PgmHandle = 0L;
1058 sdata.Reserved = 0;
1059 sdata.PgmControl = (USHORT) ((SSF_CONTROL_NOAUTOCLOSE * ((type & 15) == SEPARATEKEEP)) |
[105]1060 (SSF_CONTROL_MAXIMIZE * ((type & MAXIMIZED) != 0)) |
1061 (SSF_CONTROL_MINIMIZE * ((type & MINIMIZED) != 0)) |
1062 (SSF_CONTROL_INVISIBLE * ((type & INVISIBLE) != 0)));
[540]1063 if (pszDirectory && *pszDirectory) {
1064 save_dir2(szSavedir);
1065 switch_to(pszDirectory);
[105]1066 }
[519]1067 ret = DosStartSession(&sdata, &ulSessID, &sessPID);
[540]1068 if (pszDirectory && *pszDirectory)
1069 switch_to(szSavedir);
[330]1070 if (ret && ret != ERROR_SMG_START_IN_BACKGROUND) {
1071 Dos_Error(MB_CANCEL,ret,hwnd,pszSrcFile,__LINE__,
[540]1072 GetPString(IDS_DOSSTARTSESSIONFAILEDTEXT),pszPgm,pszArgs);
[330]1073 }
[441]1074 else if (type & WAIT) {
[105]1075 if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1076 ShowSession(hwnd, sessPID);
[2]1077
[540]1078 if (!useTermQ) {
1079 // Could not create queue - fallback - fixme to be gone?
[105]1080 STATUSDATA sd;
[2]1081
[105]1082 memset(&sd, 0, sizeof(sd));
1083 sd.Length = (USHORT) sizeof(sd);
1084 sd.SelectInd = SET_SESSION_UNCHANGED;
1085 sd.BondInd = SET_SESSION_UNCHANGED;
1086 for (ctr = 0;; ctr++)
1087 {
1088 DosSleep(200L);
[519]1089 if (DosSetSession(ulSessID, &sd)) // Check if session gone (i.e. finished)
[105]1090 break;
[519]1091 if (ctr > 10) {
1092 ShowSession(hwnd, sessPID); // Show every 2 seconds
1093 ctr = 0;
1094 }
[105]1095 }
1096 }
[441]1097 else {
[105]1098 for (ctr = 0;; ctr++)
1099 {
[540]1100 if (ctr < 20) {
1101 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1102 DCWW_NOWAIT, &bPriority, hTermQSem);
1103 if (rc == ERROR_QUE_EMPTY) {
1104 DosSleep(100);
1105 continue;
[105]1106 }
1107 }
[441]1108 else {
[540]1109 // fixme to not do this?
1110 if (ctr == 20)
1111 ShowSession(hwnd, sessPID); // Show long running session
1112 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1113 DCWW_WAIT, &bPriority, 0);
1114 }
1115
1116 if (rc) {
1117 // Oh heck
1118 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosReadQueue");
1119 DosSleep(500);
1120 continue;
1121 }
1122
1123 if (pTermInfo->usSessID == ulSessID)
1124 break; // Our session is done
1125
1126 // Requeue for other thread
1127 {
1128 static ULONG ulLastSessID;
1129 // fprintf(stderr,"runemf2 requeue other ptib %x sessId %x ti.sessId %x ti.rc %d\n",ptib,ulSessID,pTermInfo->usSessID,pTermInfo->usRC);
1130 // fixme to be gone
1131 if (ulLastSessID) {
1132 DosSleep(500);
1133 ulLastSessID = pTermInfo->usSessID;
[519]1134 }
[540]1135 // requeue and do not free yet
1136 rc = DosWriteQueue(hTermQ, rq.ulData, ulLength,(PVOID)pTermInfo, bPriority);
1137 if (rc)
1138 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosWriteQueue");
1139 DosSleep(100); // Let other thread see queue entry
[105]1140 }
[519]1141 } // for
[540]1142
1143 ret = !(!pTermInfo->usRC); // Set TRUE if rc 0
1144 // fprintf(stderr,"runemf2 term this ptib %x sessID %x rq.pid %x rq.data %x ti.rc %d\n",ptib,ulSessID,rq.pid,rq.ulData,pTermInfo->usRC);
1145 // fflush(stderr);
1146 DosFreeMem(pTermInfo);
[105]1147 }
[540]1148 } // if wait
[105]1149 else if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1150 ShowSession(hwnd, sessPID);
1151 }
1152 }
[2]1153
1154ObjectInterrupt:
1155
[540]1156 if (pszPgm)
1157 DosFreeMem(pszPgm);
1158 if (pszArgs)
1159 DosFreeMem(pszArgs);
[105]1160 return ret;
[2]1161}
1162
[519]1163//== Exec() Start application with WinStartApp ==
1164
[105]1165HAPP Exec(HWND hwndNotify, BOOL child, char *startdir, char *env,
[519]1166 PROGTYPE *progt, ULONG fl, char *formatstring,...)
[78]1167{
[105]1168 PROGDETAILS pgd;
[2]1169 register char *p;
[105]1170 char *parameters = NULL, *executable = NULL;
[519]1171 HAPP happ = (HAPP)0;
[105]1172 ULONG ulOptions = SAF_INSTALLEDCMDLINE;
1173 BOOL wasquote;
1174 va_list parguments;
[2]1175
[105]1176 if (child)
[2]1177 ulOptions |= SAF_STARTCHILDAPP;
1178
[330]1179 executable = xmallocz(MAXSTRG,pszSrcFile,__LINE__);
1180 if (executable) {
[105]1181 va_start(parguments, formatstring);
1182 vsprintf(executable, formatstring, parguments);
[2]1183 va_end(parguments);
[105]1184 strip_lead_char(" \t", executable);
[441]1185 if (*executable) {
[330]1186 parameters = xmalloc(MAXSTRG,pszSrcFile,__LINE__);
[441]1187 if (parameters) {
[105]1188 p = executable;
1189 wasquote = FALSE;
[441]1190 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
1191 if (*p == '\"') {
1192 if (!wasquote) {
[105]1193 wasquote = TRUE;
1194 memmove(p, p + 1, strlen(p));
1195 while (*p == ' ' || *p == '\t')
1196 p++;
1197 }
[441]1198 else {
[105]1199 memmove(p, p + 1, strlen(p));
1200 break;
1201 }
1202 }
1203 else
1204 p++;
1205 }
[441]1206 if (*p) {
[105]1207 *p = 0;
1208 p++;
1209 }
1210 else
1211 p = NullStr;
1212 if (*p)
1213 strcpy(parameters, p);
[2]1214
[441]1215 if (p && (!stricmp(p, ".BAT") || !stricmp(p, ".CMD"))) {
[105]1216 char *temp;
[2]1217
[330]1218 temp = xmalloc(CCHMAXPATH * 2,pszSrcFile,__LINE__);
[441]1219 if (temp) {
1220 if (!stricmp(p, ".BAT")) {
[105]1221 strcpy(temp, executable);
1222 strcpy(executable, parameters);
1223 strcpy(parameters, "/C ");
1224 strcat(parameters, temp);
1225 strcat(parameters, " ");
1226 strcat(parameters, executable);
1227 strcpy(executable, GetCmdSpec(TRUE));
1228 }
[441]1229 else if (!stricmp(p, ".CMD")) {
[105]1230 strcpy(temp, executable);
1231 strcpy(executable, parameters);
1232 strcpy(parameters, "/C ");
1233 strcat(parameters, temp);
1234 strcat(parameters, " ");
1235 strcat(parameters, executable);
1236 strcpy(executable, GetCmdSpec(FALSE));
1237 }
1238 free(temp);
1239 }
1240 }
[2]1241
[105]1242 memset(&pgd, 0, sizeof(pgd));
1243 pgd.Length = sizeof(pgd);
1244 pgd.progt = *progt;
1245 pgd.swpInitial.fl = fl;
1246 pgd.pszEnvironment = env;
1247 pgd.pszStartupDir = startdir;
1248 pgd.pszParameters = (*parameters) ? parameters : NULL;
1249 pgd.pszExecutable = executable;
1250 pgd.swpInitial.hwndInsertBehind = HWND_TOP;
1251 happ = WinStartApp(hwndNotify, &pgd, NULL, NULL, ulOptions);
1252 free(parameters);
[2]1253 }
1254 }
1255 free(executable);
1256 }
1257 return happ;
1258}
Note: See TracBrowser for help on using the repository browser.