source: trunk/dll/systemf.c@ 552

Last change on this file since 552 was 552, checked in by Gregg Young, 18 years ago

font cleanup; new image and archiver masks; messages moved to string file; new drive flags including David's icons mostly working

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