source: trunk/dll/systemf.c@ 920

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

Cleanup of NormalizeCmdLine moved to pathutil.c

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