source: trunk/dll/systemf.c@ 519

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

runemf2: temp fix for hung windows caused by termq errors

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