source: trunk/dll/systemf.c@ 540

Last change on this file since 540 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
Line 
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
9 Copyright (c) 2003, 2006 Steven H.Levine
10
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
15 26 Jul 06 SHL Use convert_nl_to_nul
16 15 Aug 06 SHL More error popups
17 01 Nov 06 SHL runemf2: temp fix for hung windows caused by termq errors
18 03 Nov 06 SHL runemf2: rework termination queue logic to work for multiple threads
19
20***********************************************************************/
21
22#define INCL_WIN
23#define INCL_WINERRORS
24#define INCL_DOS
25#define INCL_DOSERRORS
26#include <os2.h>
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>
34
35#include "fm3dll.h"
36#include "fm3dlg.h"
37#include "fm3str.h"
38
39static PSZ pszSrcFile = __FILE__;
40
41#pragma alloc_text(SYSTEMF,ShowSession,ExecOnList,runemf2)
42
43#define MAXSTRG (4096) /* used to build command line strings */
44
45//== ShowSession() bring session for foreground ==
46
47BOOL ShowSession(HWND hwnd, PID pid)
48{
49 HSWITCH hswitch;
50 SWCNTRL swctl;
51 ULONG rc;
52
53 hswitch = WinQuerySwitchHandle(pid ? (HWND)0 : hwnd, pid);
54 if (hswitch) {
55 rc = WinQuerySwitchEntry(hswitch, &swctl);
56 if (!rc) {
57 if (swctl.idProcess == pid && swctl.uchVisibility == SWL_VISIBLE)
58 rc = WinSwitchToProgram(hswitch);
59 if (!rc)
60 return TRUE;
61 // else saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Failed: %lu/%lx",rc,rc);
62
63 }
64 }
65 return FALSE;
66}
67
68//== ExecOnList() Invoke runemf2 for command and file/directory list ==
69
70int ExecOnList(HWND hwnd, char *command, int flags, char *tpath,
71 char **list, char *prompt)
72{
73 /* executes the command once for all files in list */
74
75 char path[CCHMAXPATH], commandline[2048], modpath[CCHMAXPATH], listfile[CCHMAXPATH],
76 *p, *pp, drive, *file, *ext, *dot;
77 register int x;
78 BOOL spaces;
79
80 if (!command || !*command) {
81 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
82 return -1;
83 }
84 *listfile = 0;
85 bstrip(command);
86
87 *path = 0;
88 if (tpath && *tpath)
89 strcpy(path, tpath);
90 else if (*command != '<' || !strchr(command, '>')) {
91 strcpy(path, command + (*command == '"'));
92 if (*command == '\"')
93 p = strchr(path, '\"');
94 else
95 p = strchr(path, ' ');
96 if (p)
97 *p = 0;
98 p = strrchr(path, '\\');
99 if (!p)
100 p = strrchr(path, ':');
101 if (p) {
102 if (*p == ':') {
103 p++;
104 *p = '\\';
105 p++;
106 }
107 *p = 0;
108 }
109 else
110 *path = 0;
111 }
112 if (!*path) {
113 if (list && list[0])
114 strcpy(path, list[0]);
115 p = strrchr(path, '\\');
116 if (!p)
117 p = strrchr(path, ':');
118 if (p) {
119 if (*p == ':') {
120 p++;
121 *p = '\\';
122 p++;
123 }
124 *p = 0;
125 }
126 else
127 *path = 0;
128 }
129 *modpath = 0;
130 if (list && list[0])
131 strcpy(modpath, list[0]);
132 p = strrchr(modpath, '\\');
133 if (!p)
134 p = strrchr(modpath, ':');
135 if (p) {
136 if (*p == ':') {
137 p++;
138 *p = '\\';
139 p++;
140 }
141 *p = 0;
142 }
143 else
144 *modpath = 0;
145 if (!*modpath)
146 strcpy(modpath, path);
147 if (*path)
148 MakeFullName(path);
149 if (*modpath)
150 MakeFullName(modpath);
151 if (IsFullName(path))
152 drive = toupper(*path);
153 else
154 drive = 0;
155
156 p = command; // substitue for special % sequences
157
158 pp = commandline;
159 *commandline = 0;
160 while (*p) {
161 if (*p == '%') {
162 switch (*(p + 1)) {
163 case '!': /* write list to file, add filename */
164 if (list) {
165 if (!*listfile) {
166 FILE *fp;
167
168 save_dir2(listfile);
169 if (listfile[strlen(listfile) - 1] != '\\')
170 strcat(listfile, "\\");
171 sprintf(&listfile[strlen(listfile)], "%s%03x",
172 LISTTEMPROOT, (clock() & 4095L));
173 fp = xfopen(listfile, "w",pszSrcFile,__LINE__);
174 if (fp) {
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;
189
190 case 'c': /* add name of command processor */
191 {
192 char *env = GetCmdSpec(FALSE);
193
194 if (needs_quoting(env) && !strchr(env, '\"')) {
195 *pp = '\"';
196 pp++;
197 spaces = TRUE;
198 }
199 else
200 spaces = FALSE;
201 strcpy(pp, env);
202 p += 2;
203 pp += strlen(env);
204 if (spaces) {
205 *pp = '\"';
206 pp++;
207 }
208 }
209 break;
210
211 case 't': /* add Target directory */
212 if (needs_quoting(targetdir) && !strchr(targetdir, '\"')) {
213 *pp = '\"';
214 pp++;
215 spaces = TRUE;
216 }
217 else
218 spaces = FALSE;
219 strcpy(pp, targetdir);
220 p += 2;
221 pp += strlen(targetdir);
222 if (spaces) {
223 *pp = '\"';
224 pp++;
225 }
226 break;
227
228 case '$': /* add drive letter */
229 if (drive)
230 *pp = drive;
231 else {
232 ULONG ulDriveNum = 3L, ulDriveMap;
233
234 DosQCurDisk(&ulDriveNum, &ulDriveMap);
235 *pp = (char) (ulDriveNum + '@');
236 }
237 pp++;
238 p += 2;
239 break;
240
241 case 'U': /* add path of first list component */
242 case 'u':
243 if (*modpath) {
244 if (needs_quoting(modpath) && !strchr(modpath, '\"')) {
245 spaces = TRUE;
246 *pp = '\"';
247 pp++;
248 }
249 else
250 spaces = FALSE;
251 if (*(p + 1) == 'u') {
252 strcpy(pp, modpath);
253 pp += strlen(modpath);
254 }
255 else {
256 strcpy(pp, modpath + 2);
257 pp += strlen(modpath + 2);
258 }
259 if (spaces) {
260 if (modpath[strlen(modpath) - 1] == '\\') {
261 *pp = '\\';
262 pp++;
263 }
264 *pp = '\"';
265 pp++;
266 }
267 }
268 else {
269 char temp[CCHMAXPATH];
270
271 save_dir2(temp);
272 if (needs_quoting(temp) && !strchr(temp, '\"')) {
273 spaces = TRUE;
274 *pp = '\"';
275 pp++;
276 }
277 else
278 spaces = FALSE;
279 strcpy(pp, temp);
280 pp += strlen(temp);
281 if (spaces) {
282 if (temp[strlen(temp) - 1] == '\\') {
283 *pp = '\\';
284 pp++;
285 }
286 *pp = '\"';
287 pp++;
288 }
289 }
290 p += 2;
291 break;
292
293 case 'P': /* add path of execution */
294 case 'p':
295 if (*path) {
296 if (needs_quoting(path) && !strchr(path, '\"')) {
297 spaces = TRUE;
298 *pp = '\"';
299 pp++;
300 }
301 else
302 spaces = FALSE;
303 if (*(p + 1) == 'p') {
304 strcpy(pp, path);
305 pp += strlen(path);
306 }
307 else {
308 strcpy(pp, path + 2);
309 pp += strlen(path + 2);
310 }
311 if (spaces) {
312 if (path[strlen(path) - 1] == '\\') {
313 *pp = '\\';
314 pp++;
315 }
316 *pp = '\"';
317 pp++;
318 }
319 }
320 else {
321 char temp[CCHMAXPATH];
322
323 save_dir2(temp);
324 if (needs_quoting(temp) && !strchr(temp, '\"')) {
325 spaces = TRUE;
326 *pp = '\"';
327 pp++;
328 }
329 else
330 spaces = FALSE;
331 strcpy(pp, temp);
332 pp += strlen(temp);
333 if (spaces) {
334 if (temp[strlen(temp) - 1] == '\\') {
335 *pp = '\\';
336 pp++;
337 }
338 *pp = '\"';
339 pp++;
340 }
341 }
342 p += 2;
343 break;
344
345 case 'D':
346 if (hwndMain) {
347 PCNRITEM pci;
348
349 pci = (PCNRITEM) WinSendMsg(WinWindowFromID(WinWindowFromID(
350 hwndTree, FID_CLIENT), TREE_CNR),
351 CM_QUERYRECORDEMPHASIS,
352 MPFROMLONG(CMA_FIRST),
353 MPFROMSHORT(CRA_CURSORED));
354 if (pci && (int) pci != -1 && *pci -> szFileName) {
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);
366 if (spaces) {
367 *pp = '\"';
368 pp++;
369 }
370 }
371 }
372 p += 2;
373 break;
374
375 case 'd':
376 if (hwndMain) {
377 HENUM henum;
378 char retstr[CCHMAXPATH];
379 HWND hwndC, hwndDir;
380 USHORT id;
381 BOOL first = TRUE;
382
383 henum = WinBeginEnumWindows(hwndMain);
384 while ((hwndC = WinGetNextWindow(henum)) != NULLHANDLE) {
385 if (hwndC != hwndTree) {
386 id = WinQueryWindowUShort(hwndC, QWS_ID);
387 if (id) {
388 hwndDir = WinWindowFromID(hwndC, FID_CLIENT);
389 if (hwndDir) {
390 hwndDir = WinWindowFromID(hwndDir, DIR_CNR);
391 if (hwndDir) {
392 *retstr = 0;
393 WinSendMsg(hwndC, UM_CONTAINERDIR, MPFROMP(retstr), MPVOID);
394 if (*retstr) {
395 if (!first) {
396 *pp = ' ';
397 pp++;
398 }
399 first = FALSE;
400 if (needs_quoting(retstr) && !strchr(retstr, '\"')) {
401 *pp = '\"';
402 pp++;
403 spaces = TRUE;
404 }
405 else
406 spaces = FALSE;
407 strcpy(pp, retstr);
408 pp += strlen(retstr);
409 if (spaces) {
410 *pp = '\"';
411 pp++;
412 }
413 }
414 }
415 }
416 }
417 }
418 }
419 WinEndEnumWindows(henum);
420 }
421 p += 2;
422 break;
423
424 case '%':
425 *pp = '%';
426 pp++;
427 p += 2;
428 break;
429
430 case 'R':
431 case 'F':
432 case 'A':
433 case 'r':
434 case 'f':
435 case 'a':
436 case 'e':
437 if (list) {
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++;
451 switch (*(p + 1)) {
452 case 'R':
453 case 'r':
454 if (pp + strlen(list[x]) > commandline + 1250)
455 goto BreakOut;
456 if (*(p + 1) == 'r') {
457 strcpy(pp, list[x]);
458 pp += strlen(list[x]);
459 }
460 else {
461 strcpy(pp, list[x] + 2);
462 pp += strlen(list[x] + 2);
463 }
464 break;
465
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;
472 if (needs_quoting(file)) {
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 = '.';
483 if (spaces) {
484 if (*(pp - 1) != '\"') {
485 *pp = '\"';
486 pp++;
487 }
488 }
489 break;
490
491 case 'A':
492 case 'a':
493 if (pp + strlen(list[x]) > commandline + 1250)
494 goto BreakOut;
495 if (needs_quoting(list[x]) && !strchr(list[x], '\"')) {
496 spaces = TRUE;
497 *pp = '\"';
498 pp++;
499 }
500 else
501 spaces = FALSE;
502 if (*(p + 1) == 'a') {
503 strcpy(pp, list[x]);
504 pp += strlen(list[x]);
505 }
506 else {
507 strcpy(pp, list[x] + 2);
508 pp += strlen(list[x] + 2);
509 }
510 if (spaces) {
511 if (list[x][strlen(list[x]) - 1] == '\\') {
512 *pp = '\\';
513 pp++;
514 }
515 *pp = '\"';
516 pp++;
517 }
518 break;
519
520 case 'e':
521 if (ext) {
522 if (pp + strlen(ext) > commandline + 1250)
523 goto BreakOut;
524 if (needs_quoting(ext)) {
525 spaces = TRUE;
526 *pp = '\"';
527 pp++;
528 }
529 else
530 spaces = FALSE;
531 strcpy(pp, ext);
532 pp += strlen(ext);
533 if (spaces) {
534 if (*(pp - 1) != '\"') {
535 *pp = '\"';
536 pp++;
537 }
538 }
539 }
540 break;
541 }
542 if (list[x + 1]) {
543 *pp = ' ';
544 pp++;
545 }
546 }
547 }
548 p += 2;
549 break;
550
551 default:
552 *pp = *p;
553 p++;
554 pp++;
555 break;
556 }
557 }
558 else {
559 *pp = *p;
560 pp++;
561 p++;
562 }
563 *pp = 0;
564 }
565
566BreakOut:
567
568 {
569 EXECARGS ex;
570 ULONG size;
571 int ret;
572
573 memset(&ex, 0, sizeof(EXECARGS));
574 size = sizeof(ex.environment) - 1;
575 PrfQueryProfileData(fmprof, FM3Str, command, ex.environment, &size);
576 if (flags & PROMPT) {
577 /* allow editing command line */
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 }
595}
596
597//== runemf2() run requested app, return -1 if problem starting else return app rc ==
598
599int runemf2(int type, HWND hwnd, char *pszDirectory, char *pszEnvironment,
600 char *formatstring,...)
601{
602 /* example:
603
604 * status = runemf2(SEPARATE | WINDOWED,
605 * hwnd,
606 * NullStr,
607 * NULL,
608 * "%s /C %s",
609 * getenv("COMSPEC"),
610 * batchfilename);
611 *
612 * use (HWND)0 for hwnd if window handle not handy.
613 */
614
615 /*
616 * type bitmapped flag -- see FM3DLL.H
617 */
618
619 va_list parguments;
620 int ret = -1;
621 RESULTCODES results;
622 STARTDATA sdata;
623 REQUESTDATA rq;
624 ULONG ulSessID, apptype, ulLength, ctr;
625 PID sessPID;
626 BOOL wasquote;
627 char *pszPgm, *pszArgs = NULL;
628 char szObject[32] = "", *p, szSavedir[CCHMAXPATH];
629 BOOL useTermQ = FALSE;
630 char szTempdir[CCHMAXPATH];
631
632 typedef struct {
633 USHORT usSessID;
634 USHORT usRC;
635 } TERMINFO;
636
637 TERMINFO *pTermInfo;
638 BYTE bPriority;
639 APIRET rc;
640 PIB *ppib;
641 TIB *ptib;
642
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,
651 FIL_QUERYFULLNAME,
652 szTempdir,
653 sizeof(szTempdir)))
654 pszDirectory = szTempdir;
655 }
656
657 if (!hwnd)
658 hwnd = HWND_DESKTOP;
659
660 rc = DosAllocMem((PVOID)&pszPgm,
661 MAXSTRG,
662 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
663 if (rc) {
664 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
665 return -1;
666 }
667
668 *szSavedir = 0;
669
670 *pszPgm = 0;
671 va_start(parguments,
672 formatstring);
673 vsprintf(pszPgm,
674 formatstring,
675 parguments);
676 va_end(parguments);
677
678 if (pszEnvironment) {
679 p = &pszEnvironment[strlen(pszEnvironment)] + 1;
680 *p = 0;
681 p = pszEnvironment;
682 while ((p = convert_nl_to_nul(p)) != NULL)
683 ; // loop
684 }
685
686 if (!*pszPgm) {
687 p = GetCmdSpec(FALSE);
688 strcpy(pszPgm, p);
689 if (!*pszPgm) {
690 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
691 return -1;
692 }
693 }
694
695 if (*pszPgm) {
696 if (*pszPgm == '<' && strchr(pszPgm, '>')) {
697 /* is a workplace object */
698 HOBJECT hWPSObject;
699 char temp;
700
701 p = strchr(pszPgm, '>');
702 p++;
703 temp = *p;
704 if (temp) {
705 rc = DosAllocMem((PVOID)&pszArgs,
706 MAXSTRG * 2,
707 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
708 if (rc)
709 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
710 }
711 else
712 pszArgs = NULL;
713 *p = 0;
714 /* Find the handle of the WPS object */
715 hWPSObject = WinQueryObject(pszPgm);
716 *p = temp;
717 if (hWPSObject != NULLHANDLE) {
718 if (pszArgs && *p) {
719 sprintf(pszArgs,"OPEN=DEFAULT;PARAMETERS=\"%s\"",p);
720 WinSetObjectData(hWPSObject,pszArgs);
721 }
722 else
723 WinSetObjectData(hWPSObject,"OPEN=DEFAULT");
724 ret = 0;
725 }
726 goto ObjectInterrupt;
727 }
728
729 if ((type & 15) == SYNCHRONOUS ||
730 (type & 15) == ASYNCHRONOUS ||
731 (type & 15) == DETACHED)
732 {
733 strip_lead_char(" \t", pszPgm);
734 p = pszPgm;
735 wasquote = FALSE;
736 while (*p &&
737 (wasquote ||
738 (*p != ' ' &&
739 *p != '\t')))
740 {
741 if (*p == '\"') {
742 if (!wasquote) {
743 wasquote = TRUE;
744 memmove(p,
745 p + 1,
746 strlen(p));
747 while (*p == ' ' ||
748 *p == '\t')
749 p++;
750 }
751 else {
752 memmove(p,
753 p + 1,
754 strlen(p));
755 break;
756 }
757 }
758 else
759 p++;
760 }
761 if (*p) {
762 *p = 0;
763 p++;
764 }
765 else
766 p = pszPgm;
767 p[strlen(p) + 1] = 0; /* double-terminate args */
768 if (*pszPgm) {
769 if (!strchr(pszPgm, '\\') &&
770 !strchr(pszPgm, ':') &&
771 pszDirectory &&
772 *pszDirectory)
773 {
774 save_dir2(szSavedir);
775 switch_to(pszDirectory);
776 }
777 rc = DosQAppType(pszPgm,&apptype);
778 if (!strchr(pszPgm, '\\') &&
779 !strchr(pszPgm, ':') &&
780 pszDirectory &&
781 *pszDirectory)
782 switch_to(szSavedir);
783 if (rc) {
784 // fixme to be in fm2dll.str
785 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosQAppType failed for %s.", pszPgm);
786 DosFreeMem(pszPgm);
787 if (pszArgs)
788 DosFreeMem(pszArgs);
789 return -1;
790 }
791 if (apptype) {
792 if ((apptype & FAPPTYP_DLL) || (apptype & FAPPTYP_VIRTDRV) ||
793 (apptype & FAPPTYP_PHYSDRV) || (apptype & FAPPTYP_PROTDLL))
794 {
795 // fixme to be in fm2dll.str
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);
801 return -1;
802 }
803 if ((apptype & FAPPTYP_DOS) || (apptype & FAPPTYP_WINDOWSREAL) ||
804 (apptype & FAPPTYP_WINDOWSPROT) || (apptype & 0x1000))
805 {
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);
811 return -1;
812 }
813 }
814 memset(&results, 0, sizeof(results));
815 if (pszDirectory && *pszDirectory) {
816 save_dir2(szSavedir);
817 switch_to(pszDirectory);
818 }
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);
825 if (ret) {
826 Dos_Error(MB_ENTER,ret,hwnd,pszSrcFile,__LINE__,
827 GetPString(IDS_DOSEXECPGMFAILEDTEXT), pszPgm);
828 }
829 }
830 }
831 else {
832 if (~type & FULLSCREEN)
833 type |= WINDOWED;
834 rc = DosAllocMem((PVOID) & pszArgs, MAXSTRG * 2,
835 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
836 if (rc) {
837 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
838 DosFreeMem(pszPgm);
839 return -1;
840 }
841 *pszArgs = 0;
842 memset(&sdata, 0, sizeof(sdata));
843 strip_lead_char(" \t", pszPgm);
844 p = pszPgm;
845 wasquote = FALSE;
846 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
847 if (*p == '\"') {
848 if (!wasquote) {
849 wasquote = TRUE;
850 memmove(p, p + 1, strlen(p));
851 while (*p == ' ' || *p == '\t')
852 p++;
853 }
854 else {
855 memmove(p, p + 1, strlen(p));
856 break;
857 }
858 }
859 else
860 p++;
861 } // while
862 if (*p) {
863 *p = 0;
864 p++;
865 }
866 else
867 p = NullStr;
868 if (*p)
869 strcpy(pszArgs, p);
870
871 p = strrchr(pszPgm, '.');
872 if (p) {
873 char temp[CCHMAXPATH + 1];
874
875 if (!stricmp(p, ".BAT")) {
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
883 }
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
893 }
894 }
895
896 /* goddamned OS/2 limit */
897
898 if (strlen(pszPgm) + strlen(pszArgs) > 1024)
899 pszArgs[1024 - strlen(pszPgm)] = 0;
900
901 if (!strchr(pszPgm, '\\') &&
902 !strchr(pszPgm, ':') &&
903 pszDirectory &&
904 *pszDirectory)
905 {
906 save_dir2(szSavedir);
907 switch_to(pszDirectory);
908 }
909 rc = DosQAppType(pszPgm,&apptype);
910 if (!strchr(pszPgm, '\\') &&
911 !strchr(pszPgm, ':') &&
912 pszDirectory &&
913 *pszDirectory)
914 switch_to(szSavedir);
915 if (rc) {
916 // fixme to be in fm2dll.str
917 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosQAppType failed for %s.", pszPgm);
918 DosFreeMem(pszPgm);
919 if (pszArgs)
920 DosFreeMem(pszArgs);
921 return -1;
922 }
923
924 if (apptype) {
925 if (apptype & (FAPPTYP_DLL | FAPPTYP_VIRTDRV | FAPPTYP_PHYSDRV | FAPPTYP_PROTDLL))
926 {
927 // fixme to be in fm2dll.str
928 Runtime_Error(pszSrcFile, __LINE__, "apptype %d unexpected for %s.", pszPgm);
929 DosFreeMem(pszPgm);
930 if (pszArgs)
931 DosFreeMem(pszArgs);
932 return -1;
933 }
934 apptype &= ~FAPPTYP_BOUND;
935 if (apptype & (FAPPTYP_DOS | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
936 {
937 if (apptype & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
938 {
939 if (~type & FULLSCREEN &&
940 apptype & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
941 {
942 ret = RunSeamless(pszPgm, pszArgs, hwnd);
943 if (pszPgm)
944 DosFreeMem(pszPgm);
945 if (pszArgs)
946 DosFreeMem(pszArgs);
947 return ret ? 0 : -1;
948 }
949 else {
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");
957 }
958 }
959 else {
960 if (~type & FULLSCREEN) {
961 type |= WINDOWED;
962 apptype = SSF_TYPE_WINDOWEDVDM;
963 }
964 else {
965 type &= ~WINDOWED;
966 apptype = SSF_TYPE_VDM;
967 }
968 }
969 }
970 else if (apptype & FAPPTYP_32BIT) {
971 apptype &= ~FAPPTYP_32BIT;
972 if (apptype == FAPPTYP_WINDOWAPI)
973 apptype = SSF_TYPE_PM;
974 else if (apptype == FAPPTYP_WINDOWCOMPAT)
975 apptype = SSF_TYPE_WINDOWABLEVIO;
976 else if (apptype == FAPPTYP_NOTWINDOWCOMPAT) {
977 apptype = SSF_TYPE_FULLSCREEN;
978 type &= ~WINDOWED;
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;
988 else if (apptype == FAPPTYP_NOTWINDOWCOMPAT) {
989 type &= ~WINDOWED;
990 apptype = SSF_TYPE_FULLSCREEN;
991 }
992 else
993 apptype = SSF_TYPE_DEFAULT;
994 if ((type & FULLSCREEN || ~type & WINDOWED) &&
995 apptype == SSF_TYPE_WINDOWABLEVIO)
996 {
997 apptype = SSF_TYPE_FULLSCREEN;
998 }
999 // fixme parens?
1000 else if (type & FULLSCREEN ||
1001 (type & WINDOWED && apptype == SSF_TYPE_WINDOWEDVDM))
1002 apptype = SSF_TYPE_VDM;
1003 }
1004 if (apptype == SSF_TYPE_WINDOWEDVDM && type & SEPARATEKEEP) {
1005 type &= ~SEPARATEKEEP;
1006 type |= SEPARATE;
1007 }
1008
1009 DosGetInfoBlocks(&ptib, &ppib);
1010
1011 if (~type & WAIT)
1012 useTermQ = FALSE;
1013 else {
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
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;
1048 sdata.PgmName = pszPgm;
1049 sdata.PgmInputs = *pszArgs ? pszArgs : NULL;
1050 sdata.TermQ = useTermQ ? szTermQName : NULL;
1051 sdata.Environment = pszEnvironment;
1052 sdata.InheritOpt = SSF_INHERTOPT_PARENT;
1053 sdata.SessionType = (USHORT)apptype;
1054 sdata.ObjectBuffer = szObject;
1055 sdata.ObjectBuffLen = sizeof(szObject);
1056 sdata.IconFile = NULL;
1057 sdata.PgmHandle = 0L;
1058 sdata.Reserved = 0;
1059 sdata.PgmControl = (USHORT) ((SSF_CONTROL_NOAUTOCLOSE * ((type & 15) == SEPARATEKEEP)) |
1060 (SSF_CONTROL_MAXIMIZE * ((type & MAXIMIZED) != 0)) |
1061 (SSF_CONTROL_MINIMIZE * ((type & MINIMIZED) != 0)) |
1062 (SSF_CONTROL_INVISIBLE * ((type & INVISIBLE) != 0)));
1063 if (pszDirectory && *pszDirectory) {
1064 save_dir2(szSavedir);
1065 switch_to(pszDirectory);
1066 }
1067 ret = DosStartSession(&sdata, &ulSessID, &sessPID);
1068 if (pszDirectory && *pszDirectory)
1069 switch_to(szSavedir);
1070 if (ret && ret != ERROR_SMG_START_IN_BACKGROUND) {
1071 Dos_Error(MB_CANCEL,ret,hwnd,pszSrcFile,__LINE__,
1072 GetPString(IDS_DOSSTARTSESSIONFAILEDTEXT),pszPgm,pszArgs);
1073 }
1074 else if (type & WAIT) {
1075 if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1076 ShowSession(hwnd, sessPID);
1077
1078 if (!useTermQ) {
1079 // Could not create queue - fallback - fixme to be gone?
1080 STATUSDATA sd;
1081
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);
1089 if (DosSetSession(ulSessID, &sd)) // Check if session gone (i.e. finished)
1090 break;
1091 if (ctr > 10) {
1092 ShowSession(hwnd, sessPID); // Show every 2 seconds
1093 ctr = 0;
1094 }
1095 }
1096 }
1097 else {
1098 for (ctr = 0;; ctr++)
1099 {
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;
1106 }
1107 }
1108 else {
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;
1134 }
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
1140 }
1141 } // for
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);
1147 }
1148 } // if wait
1149 else if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1150 ShowSession(hwnd, sessPID);
1151 }
1152 }
1153
1154ObjectInterrupt:
1155
1156 if (pszPgm)
1157 DosFreeMem(pszPgm);
1158 if (pszArgs)
1159 DosFreeMem(pszArgs);
1160 return ret;
1161}
1162
1163//== Exec() Start application with WinStartApp ==
1164
1165HAPP Exec(HWND hwndNotify, BOOL child, char *startdir, char *env,
1166 PROGTYPE *progt, ULONG fl, char *formatstring,...)
1167{
1168 PROGDETAILS pgd;
1169 register char *p;
1170 char *parameters = NULL, *executable = NULL;
1171 HAPP happ = (HAPP)0;
1172 ULONG ulOptions = SAF_INSTALLEDCMDLINE;
1173 BOOL wasquote;
1174 va_list parguments;
1175
1176 if (child)
1177 ulOptions |= SAF_STARTCHILDAPP;
1178
1179 executable = xmallocz(MAXSTRG,pszSrcFile,__LINE__);
1180 if (executable) {
1181 va_start(parguments, formatstring);
1182 vsprintf(executable, formatstring, parguments);
1183 va_end(parguments);
1184 strip_lead_char(" \t", executable);
1185 if (*executable) {
1186 parameters = xmalloc(MAXSTRG,pszSrcFile,__LINE__);
1187 if (parameters) {
1188 p = executable;
1189 wasquote = FALSE;
1190 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
1191 if (*p == '\"') {
1192 if (!wasquote) {
1193 wasquote = TRUE;
1194 memmove(p, p + 1, strlen(p));
1195 while (*p == ' ' || *p == '\t')
1196 p++;
1197 }
1198 else {
1199 memmove(p, p + 1, strlen(p));
1200 break;
1201 }
1202 }
1203 else
1204 p++;
1205 }
1206 if (*p) {
1207 *p = 0;
1208 p++;
1209 }
1210 else
1211 p = NullStr;
1212 if (*p)
1213 strcpy(parameters, p);
1214
1215 if (p && (!stricmp(p, ".BAT") || !stricmp(p, ".CMD"))) {
1216 char *temp;
1217
1218 temp = xmalloc(CCHMAXPATH * 2,pszSrcFile,__LINE__);
1219 if (temp) {
1220 if (!stricmp(p, ".BAT")) {
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 }
1229 else if (!stricmp(p, ".CMD")) {
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 }
1241
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);
1253 }
1254 }
1255 free(executable);
1256 }
1257 return happ;
1258}
Note: See TracBrowser for help on using the repository browser.